4
.gitignore
vendored
4
.gitignore
vendored
@@ -34,3 +34,7 @@ build/
|
|||||||
|
|
||||||
### Mac ###
|
### Mac ###
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
### Project Specific ###
|
||||||
|
tmp/
|
||||||
|
uploads/
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ services:
|
|||||||
- "3306:3306"
|
- "3306:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
- ./sql:/docker-entrypoint-initdb.d
|
- ./src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql
|
||||||
|
- ./src/main/resources/data.sql:/docker-entrypoint-initdb.d/02-data.sql
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"]
|
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
5
pom.xml
5
pom.xml
@@ -43,6 +43,11 @@
|
|||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.petshop.backend.config;
|
|||||||
|
|
||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
import com.petshop.backend.repository.UserRepository;
|
import com.petshop.backend.repository.UserRepository;
|
||||||
|
import com.petshop.backend.service.UserBusinessLinkageService;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -11,28 +12,138 @@ public class DataInitializer implements CommandLineRunner {
|
|||||||
|
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final UserBusinessLinkageService userBusinessLinkageService;
|
||||||
|
|
||||||
public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder) {
|
public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.userBusinessLinkageService = userBusinessLinkageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) {
|
public void run(String... args) {
|
||||||
if (userRepository.findByUsername("admin").isEmpty()) {
|
System.out.println("==== DataInitializer: Starting user creation ====");
|
||||||
User admin = new User();
|
|
||||||
|
User admin = userRepository.findByUsername("admin").orElse(null);
|
||||||
|
if (admin == null) {
|
||||||
|
System.out.println("Creating admin user...");
|
||||||
|
admin = new User();
|
||||||
admin.setUsername("admin");
|
admin.setUsername("admin");
|
||||||
admin.setPassword(passwordEncoder.encode("admin123"));
|
admin.setPassword(passwordEncoder.encode("admin123"));
|
||||||
|
admin.setEmail("admin@petshop.com");
|
||||||
|
admin.setFullName("Admin User");
|
||||||
admin.setRole(User.Role.ADMIN);
|
admin.setRole(User.Role.ADMIN);
|
||||||
userRepository.save(admin);
|
admin.setActive(true);
|
||||||
|
admin = userRepository.save(admin);
|
||||||
|
System.out.println("Admin user created successfully");
|
||||||
|
} else {
|
||||||
|
System.out.println("Admin user already exists");
|
||||||
|
// Normalize missing fields if needed
|
||||||
|
boolean updated = false;
|
||||||
|
if (admin.getFullName() == null || admin.getFullName().isEmpty()) {
|
||||||
|
admin.setFullName("Admin User");
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
|
if (admin.getEmail() == null || admin.getEmail().isEmpty()) {
|
||||||
|
admin.setEmail("admin@petshop.com");
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (admin.getActive() == null) {
|
||||||
|
admin.setActive(true);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (admin.getRole() == null) {
|
||||||
|
admin.setRole(User.Role.ADMIN);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
admin = userRepository.save(admin);
|
||||||
|
System.out.println("Admin user normalized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure linked employee
|
||||||
|
userBusinessLinkageService.ensureLinkedEmployee(admin);
|
||||||
|
|
||||||
if (userRepository.findByUsername("staff").isEmpty()) {
|
User staff = userRepository.findByUsername("staff").orElse(null);
|
||||||
User staff = new User();
|
if (staff == null) {
|
||||||
|
System.out.println("Creating staff user...");
|
||||||
|
staff = new User();
|
||||||
staff.setUsername("staff");
|
staff.setUsername("staff");
|
||||||
staff.setPassword(passwordEncoder.encode("staff123"));
|
staff.setPassword(passwordEncoder.encode("staff123"));
|
||||||
|
staff.setEmail("staff@petshop.com");
|
||||||
|
staff.setFullName("Staff User");
|
||||||
staff.setRole(User.Role.STAFF);
|
staff.setRole(User.Role.STAFF);
|
||||||
userRepository.save(staff);
|
staff.setActive(true);
|
||||||
|
staff = userRepository.save(staff);
|
||||||
|
System.out.println("Staff user created successfully");
|
||||||
|
} else {
|
||||||
|
System.out.println("Staff user already exists");
|
||||||
|
// Normalize missing fields if needed
|
||||||
|
boolean updated = false;
|
||||||
|
if (staff.getFullName() == null || staff.getFullName().isEmpty()) {
|
||||||
|
staff.setFullName("Staff User");
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (staff.getEmail() == null || staff.getEmail().isEmpty()) {
|
||||||
|
staff.setEmail("staff@petshop.com");
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (staff.getActive() == null) {
|
||||||
|
staff.setActive(true);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (staff.getRole() == null) {
|
||||||
|
staff.setRole(User.Role.STAFF);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
staff = userRepository.save(staff);
|
||||||
|
System.out.println("Staff user normalized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Ensure linked employee
|
||||||
|
userBusinessLinkageService.ensureLinkedEmployee(staff);
|
||||||
|
|
||||||
|
User customer = userRepository.findByUsername("customer").orElse(null);
|
||||||
|
if (customer == null) {
|
||||||
|
System.out.println("Creating customer user...");
|
||||||
|
customer = new User();
|
||||||
|
customer.setUsername("customer");
|
||||||
|
customer.setPassword(passwordEncoder.encode("customer123"));
|
||||||
|
customer.setEmail("customer@petshop.com");
|
||||||
|
customer.setFullName("Test Customer");
|
||||||
|
customer.setRole(User.Role.CUSTOMER);
|
||||||
|
customer.setActive(true);
|
||||||
|
customer = userRepository.save(customer);
|
||||||
|
System.out.println("Customer user created successfully");
|
||||||
|
} else {
|
||||||
|
System.out.println("Customer user already exists");
|
||||||
|
// Normalize missing fields if needed
|
||||||
|
boolean updated = false;
|
||||||
|
if (customer.getFullName() == null || customer.getFullName().isEmpty()) {
|
||||||
|
customer.setFullName("Test Customer");
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (customer.getEmail() == null || customer.getEmail().isEmpty()) {
|
||||||
|
customer.setEmail("customer@petshop.com");
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (customer.getActive() == null) {
|
||||||
|
customer.setActive(true);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (customer.getRole() == null) {
|
||||||
|
customer.setRole(User.Role.CUSTOMER);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
customer = userRepository.save(customer);
|
||||||
|
System.out.println("Customer user normalized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure linked customer
|
||||||
|
userBusinessLinkageService.ensureLinkedCustomer(customer);
|
||||||
|
|
||||||
|
System.out.println("==== DataInitializer: Completed ====");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.petshop.backend.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||||
|
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocketMessageBroker
|
||||||
|
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageBroker(MessageBrokerRegistry config) {
|
||||||
|
config.enableSimpleBroker("/topic", "/queue");
|
||||||
|
config.setApplicationDestinationPrefixes("/app");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||||
|
registry.addEndpoint("/ws/chat")
|
||||||
|
.setAllowedOriginPatterns("*")
|
||||||
|
.withSockJS();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,19 @@ package com.petshop.backend.controller;
|
|||||||
import com.petshop.backend.dto.adoption.AdoptionRequest;
|
import com.petshop.backend.dto.adoption.AdoptionRequest;
|
||||||
import com.petshop.backend.dto.adoption.AdoptionResponse;
|
import com.petshop.backend.dto.adoption.AdoptionResponse;
|
||||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
import com.petshop.backend.service.AdoptionService;
|
import com.petshop.backend.service.AdoptionService;
|
||||||
|
import com.petshop.backend.util.AuthenticationHelper;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -16,29 +23,61 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
public class AdoptionController {
|
public class AdoptionController {
|
||||||
|
|
||||||
private final AdoptionService adoptionService;
|
private final AdoptionService adoptionService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
public AdoptionController(AdoptionService adoptionService) {
|
public AdoptionController(AdoptionService adoptionService, UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
this.adoptionService = adoptionService;
|
this.adoptionService = adoptionService;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Page<AdoptionResponse>> getAllAdoptions(
|
public ResponseEntity<Page<AdoptionResponse>> getAllAdoptions(
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, pageable));
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, pageable, customerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AdoptionResponse> getAdoptionById(@PathVariable Long id) {
|
public ResponseEntity<AdoptionResponse> getAdoptionById(@PathVariable Long id) {
|
||||||
return ResponseEntity.ok(adoptionService.getAdoptionById(id));
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(adoptionService.getAdoptionById(id, customerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AdoptionResponse> createAdoption(@Valid @RequestBody AdoptionRequest request) {
|
public ResponseEntity<AdoptionResponse> createAdoption(@Valid @RequestBody AdoptionRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(adoptionService.createAdoption(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(adoptionService.createAdoption(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AdoptionResponse> updateAdoption(
|
public ResponseEntity<AdoptionResponse> updateAdoption(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody AdoptionRequest request) {
|
@Valid @RequestBody AdoptionRequest request) {
|
||||||
@@ -46,12 +85,14 @@ public class AdoptionController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> deleteAdoption(@PathVariable Long id) {
|
public ResponseEntity<Void> deleteAdoption(@PathVariable Long id) {
|
||||||
adoptionService.deleteAdoption(id);
|
adoptionService.deleteAdoption(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeleteAdoptions(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeleteAdoptions(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
adoptionService.bulkDeleteAdoptions(request);
|
adoptionService.bulkDeleteAdoptions(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -3,12 +3,19 @@ package com.petshop.backend.controller;
|
|||||||
import com.petshop.backend.dto.appointment.AppointmentRequest;
|
import com.petshop.backend.dto.appointment.AppointmentRequest;
|
||||||
import com.petshop.backend.dto.appointment.AppointmentResponse;
|
import com.petshop.backend.dto.appointment.AppointmentResponse;
|
||||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
import com.petshop.backend.service.AppointmentService;
|
import com.petshop.backend.service.AppointmentService;
|
||||||
|
import com.petshop.backend.util.AuthenticationHelper;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@@ -19,29 +26,61 @@ import java.util.List;
|
|||||||
public class AppointmentController {
|
public class AppointmentController {
|
||||||
|
|
||||||
private final AppointmentService appointmentService;
|
private final AppointmentService appointmentService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
public AppointmentController(AppointmentService appointmentService) {
|
public AppointmentController(AppointmentService appointmentService, UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
this.appointmentService = appointmentService;
|
this.appointmentService = appointmentService;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Page<AppointmentResponse>> getAllAppointments(
|
public ResponseEntity<Page<AppointmentResponse>> getAllAppointments(
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(appointmentService.getAllAppointments(q, pageable));
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(appointmentService.getAllAppointments(q, pageable, customerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AppointmentResponse> getAppointmentById(@PathVariable Long id) {
|
public ResponseEntity<AppointmentResponse> getAppointmentById(@PathVariable Long id) {
|
||||||
return ResponseEntity.ok(appointmentService.getAppointmentById(id));
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(appointmentService.getAppointmentById(id, customerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AppointmentResponse> createAppointment(@Valid @RequestBody AppointmentRequest request) {
|
public ResponseEntity<AppointmentResponse> createAppointment(@Valid @RequestBody AppointmentRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(appointmentService.createAppointment(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(appointmentService.createAppointment(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<AppointmentResponse> updateAppointment(
|
public ResponseEntity<AppointmentResponse> updateAppointment(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody AppointmentRequest request) {
|
@Valid @RequestBody AppointmentRequest request) {
|
||||||
@@ -49,12 +88,14 @@ public class AppointmentController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> deleteAppointment(@PathVariable Long id) {
|
public ResponseEntity<Void> deleteAppointment(@PathVariable Long id) {
|
||||||
appointmentService.deleteAppointment(id);
|
appointmentService.deleteAppointment(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeleteAppointments(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeleteAppointments(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
appointmentService.bulkDeleteAppointments(request);
|
appointmentService.bulkDeleteAppointments(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package com.petshop.backend.controller;
|
package com.petshop.backend.controller;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.auth.AvatarUploadResponse;
|
||||||
import com.petshop.backend.dto.auth.LoginRequest;
|
import com.petshop.backend.dto.auth.LoginRequest;
|
||||||
import com.petshop.backend.dto.auth.LoginResponse;
|
import com.petshop.backend.dto.auth.LoginResponse;
|
||||||
|
import com.petshop.backend.dto.auth.ProfileUpdateRequest;
|
||||||
|
import com.petshop.backend.dto.auth.RegisterRequest;
|
||||||
|
import com.petshop.backend.dto.auth.RegisterResponse;
|
||||||
import com.petshop.backend.dto.auth.UserInfoResponse;
|
import com.petshop.backend.dto.auth.UserInfoResponse;
|
||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
import com.petshop.backend.repository.UserRepository;
|
import com.petshop.backend.repository.UserRepository;
|
||||||
import com.petshop.backend.security.JwtUtil;
|
import com.petshop.backend.security.JwtUtil;
|
||||||
|
import com.petshop.backend.service.UserBusinessLinkageService;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -18,9 +23,17 @@ import org.springframework.security.core.userdetails.UserDetails;
|
|||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
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.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/auth")
|
@RequestMapping("/api/v1/auth")
|
||||||
@@ -30,12 +43,58 @@ public class AuthController {
|
|||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final JwtUtil jwtUtil;
|
private final JwtUtil jwtUtil;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final UserBusinessLinkageService userBusinessLinkageService;
|
||||||
|
|
||||||
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder) {
|
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
|
||||||
this.authenticationManager = authenticationManager;
|
this.authenticationManager = authenticationManager;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.jwtUtil = jwtUtil;
|
this.jwtUtil = jwtUtil;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.userBusinessLinkageService = userBusinessLinkageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest request) {
|
||||||
|
if (userRepository.findByUsername(request.getUsername()).isPresent()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Username already exists");
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRepository.findByEmail(request.getEmail()).isPresent()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Email already exists");
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(request.getUsername());
|
||||||
|
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||||
|
user.setEmail(request.getEmail());
|
||||||
|
user.setFullName(request.getFullName());
|
||||||
|
user.setRole(User.Role.CUSTOMER);
|
||||||
|
user.setActive(true);
|
||||||
|
|
||||||
|
User savedUser = userRepository.save(user);
|
||||||
|
|
||||||
|
// Create or link customer record
|
||||||
|
userBusinessLinkageService.ensureLinkedCustomer(savedUser);
|
||||||
|
|
||||||
|
UserDetails userDetails = new org.springframework.security.core.userdetails.User(
|
||||||
|
savedUser.getUsername(),
|
||||||
|
savedUser.getPassword(),
|
||||||
|
java.util.Collections.emptyList()
|
||||||
|
);
|
||||||
|
|
||||||
|
String token = jwtUtil.generateToken(userDetails);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(new RegisterResponse(
|
||||||
|
savedUser.getId(),
|
||||||
|
savedUser.getUsername(),
|
||||||
|
savedUser.getEmail(),
|
||||||
|
savedUser.getRole().name(),
|
||||||
|
token
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@@ -80,14 +139,162 @@ public class AuthController {
|
|||||||
return ResponseEntity.ok(new UserInfoResponse(
|
return ResponseEntity.ok(new UserInfoResponse(
|
||||||
user.getId(),
|
user.getId(),
|
||||||
user.getUsername(),
|
user.getUsername(),
|
||||||
|
user.getEmail(),
|
||||||
|
user.getFullName(),
|
||||||
|
user.getAvatarUrl(),
|
||||||
user.getRole().name()
|
user.getRole().name()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/me")
|
||||||
|
public ResponseEntity<?> updateProfile(@Valid @RequestBody ProfileUpdateRequest request) {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String username = authentication.getName();
|
||||||
|
|
||||||
|
User user = userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
|
||||||
|
if (request.getUsername() != null && !request.getUsername().equals(user.getUsername())) {
|
||||||
|
if (userRepository.findByUsername(request.getUsername()).isPresent()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Username already exists");
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
|
||||||
|
}
|
||||||
|
user.setUsername(request.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
|
||||||
|
if (userRepository.findByEmail(request.getEmail()).isPresent()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Email already exists");
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
|
||||||
|
}
|
||||||
|
user.setEmail(request.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getFullName() != null) {
|
||||||
|
user.setFullName(request.getFullName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getPassword() != null && !request.getPassword().isEmpty()) {
|
||||||
|
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
|
User updatedUser = userRepository.save(user);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(new UserInfoResponse(
|
||||||
|
updatedUser.getId(),
|
||||||
|
updatedUser.getUsername(),
|
||||||
|
updatedUser.getEmail(),
|
||||||
|
updatedUser.getFullName(),
|
||||||
|
updatedUser.getAvatarUrl(),
|
||||||
|
updatedUser.getRole().name()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/me/avatar")
|
||||||
|
public ResponseEntity<?> uploadAvatar(@RequestParam("avatar") MultipartFile file) {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String username = authentication.getName();
|
||||||
|
|
||||||
|
User user = userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Please select a file to upload");
|
||||||
|
return ResponseEntity.badRequest().body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.getSize() > 5 * 1024 * 1024) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "File size must not exceed 5MB");
|
||||||
|
return ResponseEntity.badRequest().body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
String contentType = file.getContentType();
|
||||||
|
if (contentType == null || (!contentType.equals("image/jpeg") && !contentType.equals("image/png") && !contentType.equals("image/gif"))) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Only JPG, PNG, and GIF images are allowed");
|
||||||
|
return ResponseEntity.badRequest().body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String uploadDir = "uploads/avatars";
|
||||||
|
File directory = new File(uploadDir);
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
String extension = originalFilename != null && originalFilename.contains(".")
|
||||||
|
? originalFilename.substring(originalFilename.lastIndexOf("."))
|
||||||
|
: ".jpg";
|
||||||
|
String filename = UUID.randomUUID().toString() + extension;
|
||||||
|
Path filePath = Paths.get(uploadDir, filename);
|
||||||
|
|
||||||
|
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
|
String avatarUrl = "/uploads/avatars/" + filename;
|
||||||
|
user.setAvatarUrl(avatarUrl);
|
||||||
|
userRepository.save(user);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(new AvatarUploadResponse(avatarUrl, "Avatar uploaded successfully"));
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "Failed to upload avatar: " + e.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/me/avatar")
|
||||||
|
public ResponseEntity<?> getAvatar() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String username = authentication.getName();
|
||||||
|
|
||||||
|
User user = userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
|
||||||
|
if (user.getAvatarUrl() == null || user.getAvatarUrl().isEmpty()) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", "No avatar uploaded");
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
response.put("avatarUrl", user.getAvatarUrl());
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/me/avatar")
|
||||||
|
public ResponseEntity<?> deleteAvatar() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String username = authentication.getName();
|
||||||
|
|
||||||
|
User user = userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
|
||||||
|
if (user.getAvatarUrl() != null && !user.getAvatarUrl().isEmpty()) {
|
||||||
|
try {
|
||||||
|
Path filePath = Paths.get("." + user.getAvatarUrl());
|
||||||
|
Files.deleteIfExists(filePath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
user.setAvatarUrl(null);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
response.put("message", "Avatar deleted successfully");
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
public ResponseEntity<?> logout() {
|
public ResponseEntity<?> logout() {
|
||||||
Map<String, String> response = new HashMap<>();
|
Map<String, String> response = new HashMap<>();
|
||||||
response.put("message", "Logged out successfully");
|
response.put("message", "Logged out successfully");
|
||||||
|
response.put("note", "Token remains valid until expiration. Clear token from client storage.");
|
||||||
return ResponseEntity.ok(response);
|
return ResponseEntity.ok(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -34,11 +35,13 @@ public class CategoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<CategoryResponse> createCategory(@Valid @RequestBody CategoryRequest request) {
|
public ResponseEntity<CategoryResponse> createCategory(@Valid @RequestBody CategoryRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(categoryService.createCategory(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(categoryService.createCategory(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<CategoryResponse> updateCategory(
|
public ResponseEntity<CategoryResponse> updateCategory(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody CategoryRequest request) {
|
@Valid @RequestBody CategoryRequest request) {
|
||||||
@@ -46,12 +49,14 @@ public class CategoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> deleteCategory(@PathVariable Long id) {
|
public ResponseEntity<Void> deleteCategory(@PathVariable Long id) {
|
||||||
categoryService.deleteCategory(id);
|
categoryService.deleteCategory(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeleteCategories(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeleteCategories(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
categoryService.bulkDeleteCategories(request);
|
categoryService.bulkDeleteCategories(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package com.petshop.backend.controller;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.chat.ConversationRequest;
|
||||||
|
import com.petshop.backend.dto.chat.ConversationResponse;
|
||||||
|
import com.petshop.backend.dto.chat.MessageRequest;
|
||||||
|
import com.petshop.backend.dto.chat.MessageResponse;
|
||||||
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
|
import com.petshop.backend.service.ChatService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/chat")
|
||||||
|
public class ChatController {
|
||||||
|
|
||||||
|
private final ChatService chatService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
public ChatController(ChatService chatService, UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
|
this.chatService = chatService;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
private User getCurrentUser() {
|
||||||
|
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
return userRepository.findByUsername(userDetails.getUsername())
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/conversations")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<ConversationResponse> createConversation(@Valid @RequestBody ConversationRequest request) {
|
||||||
|
User user = getCurrentUser();
|
||||||
|
ConversationResponse response = chatService.createConversation(user.getId(), request);
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/conversations")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<List<ConversationResponse>> getConversations() {
|
||||||
|
User user = getCurrentUser();
|
||||||
|
List<ConversationResponse> conversations = chatService.getConversations(user.getId(), user.getRole());
|
||||||
|
return ResponseEntity.ok(conversations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/conversations/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<ConversationResponse> getConversation(@PathVariable Long id) {
|
||||||
|
User user = getCurrentUser();
|
||||||
|
ConversationResponse conversation = chatService.getConversation(id, user.getId(), user.getRole());
|
||||||
|
return ResponseEntity.ok(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/conversations/{id}/messages")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<MessageResponse> sendMessage(
|
||||||
|
@PathVariable Long id,
|
||||||
|
@Valid @RequestBody MessageRequest request) {
|
||||||
|
User user = getCurrentUser();
|
||||||
|
MessageResponse message = chatService.sendMessage(id, user.getId(), user.getRole(), request);
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/conversations/{id}/messages")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<List<MessageResponse>> getMessages(@PathVariable Long id) {
|
||||||
|
User user = getCurrentUser();
|
||||||
|
List<MessageResponse> messages = chatService.getMessages(id, user.getId(), user.getRole());
|
||||||
|
return ResponseEntity.ok(messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,10 +9,12 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/customers")
|
@RequestMapping("/api/v1/customers")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public class CustomerController {
|
public class CustomerController {
|
||||||
|
|
||||||
private final CustomerService customerService;
|
private final CustomerService customerService;
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.petshop.backend.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/health")
|
||||||
|
public class HealthController {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<Map<String, String>> healthCheck() {
|
||||||
|
return ResponseEntity.ok(Map.of("status", "UP"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -34,11 +35,13 @@ public class PetController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<PetResponse> createPet(@Valid @RequestBody PetRequest request) {
|
public ResponseEntity<PetResponse> createPet(@Valid @RequestBody PetRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(petService.createPet(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(petService.createPet(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<PetResponse> updatePet(
|
public ResponseEntity<PetResponse> updatePet(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody PetRequest request) {
|
@Valid @RequestBody PetRequest request) {
|
||||||
@@ -46,12 +49,14 @@ public class PetController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> deletePet(@PathVariable Long id) {
|
public ResponseEntity<Void> deletePet(@PathVariable Long id) {
|
||||||
petService.deletePet(id);
|
petService.deletePet(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeletePets(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeletePets(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
petService.bulkDeletePets(request);
|
petService.bulkDeletePets(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -34,11 +35,13 @@ public class ProductController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<ProductResponse> createProduct(@Valid @RequestBody ProductRequest request) {
|
public ResponseEntity<ProductResponse> createProduct(@Valid @RequestBody ProductRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(productService.createProduct(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(productService.createProduct(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<ProductResponse> updateProduct(
|
public ResponseEntity<ProductResponse> updateProduct(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody ProductRequest request) {
|
@Valid @RequestBody ProductRequest request) {
|
||||||
@@ -46,12 +49,14 @@ public class ProductController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
|
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
|
||||||
productService.deleteProduct(id);
|
productService.deleteProduct(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeleteProducts(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeleteProducts(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
productService.bulkDeleteProducts(request);
|
productService.bulkDeleteProducts(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package com.petshop.backend.controller;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.refund.RefundRequest;
|
||||||
|
import com.petshop.backend.dto.refund.RefundResponse;
|
||||||
|
import com.petshop.backend.dto.refund.RefundUpdateRequest;
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
|
import com.petshop.backend.service.RefundService;
|
||||||
|
import com.petshop.backend.util.AuthenticationHelper;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/refunds")
|
||||||
|
public class RefundController {
|
||||||
|
|
||||||
|
private final RefundService refundService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
public RefundController(RefundService refundService, UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
|
this.refundService = refundService;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<?> createRefund(@Valid @RequestBody RefundRequest request) {
|
||||||
|
try {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefundResponse refund = refundService.createRefund(request, customerId);
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(refund);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", e.getMessage());
|
||||||
|
return ResponseEntity.badRequest().body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<List<RefundResponse>> getAllRefunds() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RefundResponse> refunds = refundService.getAllRefunds(customerId);
|
||||||
|
return ResponseEntity.ok(refunds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<?> getRefundById(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
String role = authentication.getAuthorities().stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Long customerId = null;
|
||||||
|
if (role != null && role.equals("CUSTOMER")) {
|
||||||
|
Customer customer = AuthenticationHelper.getAuthenticatedCustomer(userRepository, customerRepository);
|
||||||
|
customerId = customer.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefundResponse refund = refundService.getRefundById(id, customerId);
|
||||||
|
return ResponseEntity.ok(refund);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", e.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
|
public ResponseEntity<?> updateRefund(@PathVariable Long id, @Valid @RequestBody RefundUpdateRequest request) {
|
||||||
|
try {
|
||||||
|
RefundResponse refund = refundService.updateRefundStatus(id, request.getStatus());
|
||||||
|
return ResponseEntity.ok(refund);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", e.getMessage());
|
||||||
|
return ResponseEntity.badRequest().body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<?> deleteRefund(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
refundService.deleteRefund(id);
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
response.put("message", "Refund deleted successfully");
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Map<String, String> error = new HashMap<>();
|
||||||
|
error.put("message", e.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -33,6 +34,7 @@ public class SaleController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<SaleResponse> createSale(@Valid @RequestBody SaleRequest request) {
|
public ResponseEntity<SaleResponse> createSale(@Valid @RequestBody SaleRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(saleService.createSale(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(saleService.createSale(request));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -34,11 +35,13 @@ public class ServiceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<ServiceResponse> createService(@Valid @RequestBody ServiceRequest request) {
|
public ResponseEntity<ServiceResponse> createService(@Valid @RequestBody ServiceRequest request) {
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(serviceService.createService(request));
|
return ResponseEntity.status(HttpStatus.CREATED).body(serviceService.createService(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<ServiceResponse> updateService(
|
public ResponseEntity<ServiceResponse> updateService(
|
||||||
@PathVariable Long id,
|
@PathVariable Long id,
|
||||||
@Valid @RequestBody ServiceRequest request) {
|
@Valid @RequestBody ServiceRequest request) {
|
||||||
@@ -46,12 +49,14 @@ public class ServiceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> deleteService(@PathVariable Long id) {
|
public ResponseEntity<Void> deleteService(@PathVariable Long id) {
|
||||||
serviceService.deleteService(id);
|
serviceService.deleteService(id);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Void> bulkDeleteServices(@Valid @RequestBody BulkDeleteRequest request) {
|
public ResponseEntity<Void> bulkDeleteServices(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
serviceService.bulkDeleteServices(request);
|
serviceService.bulkDeleteServices(request);
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
package com.petshop.backend.controller;
|
package com.petshop.backend.controller;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||||
|
import com.petshop.backend.dto.store.StoreRequest;
|
||||||
import com.petshop.backend.dto.store.StoreResponse;
|
import com.petshop.backend.dto.store.StoreResponse;
|
||||||
import com.petshop.backend.service.StoreService;
|
import com.petshop.backend.service.StoreService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/stores")
|
@RequestMapping("/api/v1/stores")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public class StoreController {
|
public class StoreController {
|
||||||
|
|
||||||
private final StoreService storeService;
|
private final StoreService storeService;
|
||||||
@@ -23,4 +29,33 @@ public class StoreController {
|
|||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(storeService.getAllStores(q, pageable));
|
return ResponseEntity.ok(storeService.getAllStores(q, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<StoreResponse> getStoreById(@PathVariable Long id) {
|
||||||
|
return ResponseEntity.ok(storeService.getStoreById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<StoreResponse> createStore(@Valid @RequestBody StoreRequest request) {
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(storeService.createStore(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public ResponseEntity<StoreResponse> updateStore(
|
||||||
|
@PathVariable Long id,
|
||||||
|
@Valid @RequestBody StoreRequest request) {
|
||||||
|
return ResponseEntity.ok(storeService.updateStore(id, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseEntity<Void> deleteStore(@PathVariable Long id) {
|
||||||
|
storeService.deleteStore(id);
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
public ResponseEntity<Void> bulkDeleteStores(@Valid @RequestBody BulkDeleteRequest request) {
|
||||||
|
storeService.bulkDeleteStores(request);
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.petshop.backend.dto.auth;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class AvatarUploadResponse {
|
||||||
|
private String avatarUrl;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public AvatarUploadResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AvatarUploadResponse(String avatarUrl, String message) {
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatarUrl() {
|
||||||
|
return avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarUrl(String avatarUrl) {
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
AvatarUploadResponse that = (AvatarUploadResponse) o;
|
||||||
|
return Objects.equals(avatarUrl, that.avatarUrl) &&
|
||||||
|
Objects.equals(message, that.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(avatarUrl, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AvatarUploadResponse{" +
|
||||||
|
"avatarUrl='" + avatarUrl + '\'' +
|
||||||
|
", message='" + message + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.petshop.backend.dto.auth;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class ProfileUpdateRequest {
|
||||||
|
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Email(message = "Email must be valid")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Size(max = 100, message = "Full name must not exceed 100 characters")
|
||||||
|
private String fullName;
|
||||||
|
|
||||||
|
@Size(min = 6, message = "Password must be at least 6 characters")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ProfileUpdateRequest that = (ProfileUpdateRequest) o;
|
||||||
|
return Objects.equals(username, that.username) &&
|
||||||
|
Objects.equals(email, that.email) &&
|
||||||
|
Objects.equals(fullName, that.fullName) &&
|
||||||
|
Objects.equals(password, that.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(username, email, fullName, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ProfileUpdateRequest{" +
|
||||||
|
"username='" + username + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
", password='" + password + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.petshop.backend.dto.auth;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RegisterRequest {
|
||||||
|
@NotBlank(message = "Username is required")
|
||||||
|
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@NotBlank(message = "Password is required")
|
||||||
|
@Size(min = 6, message = "Password must be at least 6 characters")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@NotBlank(message = "Email is required")
|
||||||
|
@Email(message = "Email must be valid")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "Full name is required")
|
||||||
|
@Size(max = 100, message = "Full name must not exceed 100 characters")
|
||||||
|
private String fullName;
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RegisterRequest that = (RegisterRequest) o;
|
||||||
|
return Objects.equals(username, that.username) &&
|
||||||
|
Objects.equals(password, that.password) &&
|
||||||
|
Objects.equals(email, that.email) &&
|
||||||
|
Objects.equals(fullName, that.fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(username, password, email, fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RegisterRequest{" +
|
||||||
|
"username='" + username + '\'' +
|
||||||
|
", password='" + password + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.petshop.backend.dto.auth;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RegisterResponse {
|
||||||
|
private Long id;
|
||||||
|
private String username;
|
||||||
|
private String email;
|
||||||
|
private String role;
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
public RegisterResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegisterResponse(Long id, String username, String email, String role, String token) {
|
||||||
|
this.id = id;
|
||||||
|
this.username = username;
|
||||||
|
this.email = email;
|
||||||
|
this.role = role;
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RegisterResponse that = (RegisterResponse) o;
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(username, that.username) &&
|
||||||
|
Objects.equals(email, that.email) &&
|
||||||
|
Objects.equals(role, that.role) &&
|
||||||
|
Objects.equals(token, that.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, username, email, role, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RegisterResponse{" +
|
||||||
|
"id=" + id +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", role='" + role + '\'' +
|
||||||
|
", token='" + token + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,14 +5,20 @@ import java.util.Objects;
|
|||||||
public class UserInfoResponse {
|
public class UserInfoResponse {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String username;
|
private String username;
|
||||||
|
private String email;
|
||||||
|
private String fullName;
|
||||||
|
private String avatarUrl;
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
public UserInfoResponse() {
|
public UserInfoResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserInfoResponse(Long id, String username, String role) {
|
public UserInfoResponse(Long id, String username, String email, String fullName, String avatarUrl, String role) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
this.email = email;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +38,30 @@ public class UserInfoResponse {
|
|||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatarUrl() {
|
||||||
|
return avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarUrl(String avatarUrl) {
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public String getRole() {
|
public String getRole() {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
@@ -45,12 +75,17 @@ public class UserInfoResponse {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
UserInfoResponse that = (UserInfoResponse) o;
|
UserInfoResponse that = (UserInfoResponse) o;
|
||||||
return Objects.equals(id, that.id) && Objects.equals(username, that.username) && Objects.equals(role, that.role);
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(username, that.username) &&
|
||||||
|
Objects.equals(email, that.email) &&
|
||||||
|
Objects.equals(fullName, that.fullName) &&
|
||||||
|
Objects.equals(avatarUrl, that.avatarUrl) &&
|
||||||
|
Objects.equals(role, that.role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id, username, role);
|
return Objects.hash(id, username, email, fullName, avatarUrl, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,6 +93,9 @@ public class UserInfoResponse {
|
|||||||
return "UserInfoResponse{" +
|
return "UserInfoResponse{" +
|
||||||
"id=" + id +
|
"id=" + id +
|
||||||
", username='" + username + '\'' +
|
", username='" + username + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
", avatarUrl='" + avatarUrl + '\'' +
|
||||||
", role='" + role + '\'' +
|
", role='" + role + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.petshop.backend.dto.chat;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public class ConversationRequest {
|
||||||
|
@NotBlank(message = "Initial message is required")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public ConversationRequest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConversationRequest(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.petshop.backend.dto.chat;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Conversation;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class ConversationResponse {
|
||||||
|
private Long id;
|
||||||
|
private Long customerId;
|
||||||
|
private Long staffId;
|
||||||
|
private String status;
|
||||||
|
private String lastMessage;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public ConversationResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConversationResponse(Long id, Long customerId, Long staffId, String status, String lastMessage, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
|
this.id = id;
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.staffId = staffId;
|
||||||
|
this.status = status;
|
||||||
|
this.lastMessage = lastMessage;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConversationResponse fromEntity(Conversation conversation, String lastMessage) {
|
||||||
|
ConversationResponse response = new ConversationResponse();
|
||||||
|
response.setId(conversation.getId());
|
||||||
|
response.setCustomerId(conversation.getCustomerId());
|
||||||
|
response.setStaffId(conversation.getStaffId());
|
||||||
|
response.setStatus(conversation.getStatus().name());
|
||||||
|
response.setLastMessage(lastMessage);
|
||||||
|
response.setCreatedAt(conversation.getCreatedAt());
|
||||||
|
response.setUpdatedAt(conversation.getUpdatedAt());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStaffId() {
|
||||||
|
return staffId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStaffId(Long staffId) {
|
||||||
|
this.staffId = staffId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastMessage() {
|
||||||
|
return lastMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastMessage(String lastMessage) {
|
||||||
|
this.lastMessage = lastMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(LocalDateTime createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.petshop.backend.dto.chat;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public class MessageRequest {
|
||||||
|
@NotBlank(message = "Message content is required")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
public MessageRequest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageRequest(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.petshop.backend.dto.chat;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Message;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class MessageResponse {
|
||||||
|
private Long id;
|
||||||
|
private Long conversationId;
|
||||||
|
private Long senderId;
|
||||||
|
private String content;
|
||||||
|
private LocalDateTime timestamp;
|
||||||
|
private Boolean isRead;
|
||||||
|
|
||||||
|
public MessageResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageResponse(Long id, Long conversationId, Long senderId, String content, LocalDateTime timestamp, Boolean isRead) {
|
||||||
|
this.id = id;
|
||||||
|
this.conversationId = conversationId;
|
||||||
|
this.senderId = senderId;
|
||||||
|
this.content = content;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.isRead = isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageResponse fromEntity(Message message) {
|
||||||
|
MessageResponse response = new MessageResponse();
|
||||||
|
response.setId(message.getId());
|
||||||
|
response.setConversationId(message.getConversationId());
|
||||||
|
response.setSenderId(message.getSenderId());
|
||||||
|
response.setContent(message.getContent());
|
||||||
|
response.setTimestamp(message.getTimestamp());
|
||||||
|
response.setIsRead(message.getIsRead());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getConversationId() {
|
||||||
|
return conversationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConversationId(Long conversationId) {
|
||||||
|
this.conversationId = conversationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSenderId() {
|
||||||
|
return senderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSenderId(Long senderId) {
|
||||||
|
this.senderId = senderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(LocalDateTime timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIsRead() {
|
||||||
|
return isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsRead(Boolean isRead) {
|
||||||
|
this.isRead = isRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.petshop.backend.dto.refund;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RefundRequest {
|
||||||
|
@NotNull(message = "Sale ID is required")
|
||||||
|
private Long saleId;
|
||||||
|
|
||||||
|
@NotBlank(message = "Reason is required")
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
public Long getSaleId() {
|
||||||
|
return saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaleId(Long saleId) {
|
||||||
|
this.saleId = saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RefundRequest that = (RefundRequest) o;
|
||||||
|
return Objects.equals(saleId, that.saleId) &&
|
||||||
|
Objects.equals(reason, that.reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(saleId, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RefundRequest{" +
|
||||||
|
"saleId=" + saleId +
|
||||||
|
", reason='" + reason + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
128
src/main/java/com/petshop/backend/dto/refund/RefundResponse.java
Normal file
128
src/main/java/com/petshop/backend/dto/refund/RefundResponse.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package com.petshop.backend.dto.refund;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RefundResponse {
|
||||||
|
private Long id;
|
||||||
|
private Long saleId;
|
||||||
|
private Long customerId;
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String reason;
|
||||||
|
private String status;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public RefundResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefundResponse(Long id, Long saleId, Long customerId, BigDecimal amount, String reason, String status, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
|
this.id = id;
|
||||||
|
this.saleId = saleId;
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.amount = amount;
|
||||||
|
this.reason = reason;
|
||||||
|
this.status = status;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSaleId() {
|
||||||
|
return saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaleId(Long saleId) {
|
||||||
|
this.saleId = saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(BigDecimal amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RefundResponse that = (RefundResponse) o;
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(saleId, that.saleId) &&
|
||||||
|
Objects.equals(customerId, that.customerId) &&
|
||||||
|
Objects.equals(amount, that.amount) &&
|
||||||
|
Objects.equals(reason, that.reason) &&
|
||||||
|
Objects.equals(status, that.status) &&
|
||||||
|
Objects.equals(createdAt, that.createdAt) &&
|
||||||
|
Objects.equals(updatedAt, that.updatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, saleId, customerId, amount, reason, status, createdAt, updatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RefundResponse{" +
|
||||||
|
"id=" + id +
|
||||||
|
", saleId=" + saleId +
|
||||||
|
", customerId=" + customerId +
|
||||||
|
", amount=" + amount +
|
||||||
|
", reason='" + reason + '\'' +
|
||||||
|
", status='" + status + '\'' +
|
||||||
|
", createdAt=" + createdAt +
|
||||||
|
", updatedAt=" + updatedAt +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.petshop.backend.dto.refund;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RefundUpdateRequest {
|
||||||
|
@NotBlank(message = "Status is required")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RefundUpdateRequest that = (RefundUpdateRequest) o;
|
||||||
|
return Objects.equals(status, that.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RefundUpdateRequest{" +
|
||||||
|
"status='" + status + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,8 @@ public class SaleRequest {
|
|||||||
|
|
||||||
private Long originalSaleId;
|
private Long originalSaleId;
|
||||||
|
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
public Long getStoreId() {
|
public Long getStoreId() {
|
||||||
return storeId;
|
return storeId;
|
||||||
}
|
}
|
||||||
@@ -60,6 +62,14 @@ public class SaleRequest {
|
|||||||
this.originalSaleId = originalSaleId;
|
this.originalSaleId = originalSaleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
@@ -69,12 +79,13 @@ public class SaleRequest {
|
|||||||
Objects.equals(paymentMethod, that.paymentMethod) &&
|
Objects.equals(paymentMethod, that.paymentMethod) &&
|
||||||
Objects.equals(items, that.items) &&
|
Objects.equals(items, that.items) &&
|
||||||
Objects.equals(isRefund, that.isRefund) &&
|
Objects.equals(isRefund, that.isRefund) &&
|
||||||
Objects.equals(originalSaleId, that.originalSaleId);
|
Objects.equals(originalSaleId, that.originalSaleId) &&
|
||||||
|
Objects.equals(customerId, that.customerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(storeId, paymentMethod, items, isRefund, originalSaleId);
|
return Objects.hash(storeId, paymentMethod, items, isRefund, originalSaleId, customerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,6 +96,7 @@ public class SaleRequest {
|
|||||||
", items=" + items +
|
", items=" + items +
|
||||||
", isRefund=" + isRefund +
|
", isRefund=" + isRefund +
|
||||||
", originalSaleId=" + originalSaleId +
|
", originalSaleId=" + originalSaleId +
|
||||||
|
", customerId=" + customerId +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.petshop.backend.dto.store;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class StoreRequest {
|
||||||
|
@NotBlank(message = "Store name is required")
|
||||||
|
private String storeName;
|
||||||
|
|
||||||
|
@NotBlank(message = "Address is required")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@NotBlank(message = "Phone is required")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "Email is required")
|
||||||
|
@Email(message = "Email must be valid")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
public String getStoreName() {
|
||||||
|
return storeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreName(String storeName) {
|
||||||
|
this.storeName = storeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhone(String phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
StoreRequest that = (StoreRequest) o;
|
||||||
|
return Objects.equals(storeName, that.storeName) &&
|
||||||
|
Objects.equals(address, that.address) &&
|
||||||
|
Objects.equals(phone, that.phone) &&
|
||||||
|
Objects.equals(email, that.email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(storeName, address, phone, email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "StoreRequest{" +
|
||||||
|
"storeName='" + storeName + '\'' +
|
||||||
|
", address='" + address + '\'' +
|
||||||
|
", phone='" + phone + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/main/java/com/petshop/backend/entity/Conversation.java
Normal file
98
src/main/java/com/petshop/backend/entity/Conversation.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package com.petshop.backend.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "conversation")
|
||||||
|
public class Conversation {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private Long staffId;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(length = 20, nullable = false)
|
||||||
|
private ConversationStatus status = ConversationStatus.OPEN;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "created_at", nullable = false, updatable = false)
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updated_at", nullable = false)
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public enum ConversationStatus {
|
||||||
|
OPEN, CLOSED
|
||||||
|
}
|
||||||
|
|
||||||
|
public Conversation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Conversation(Long id, Long customerId, Long staffId, ConversationStatus status, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
|
this.id = id;
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.staffId = staffId;
|
||||||
|
this.status = status;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStaffId() {
|
||||||
|
return staffId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStaffId(Long staffId) {
|
||||||
|
this.staffId = staffId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConversationStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(ConversationStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(LocalDateTime createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,9 @@ public class Customer {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long customerId;
|
private Long customerId;
|
||||||
|
|
||||||
|
@Column(name = "user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
@Column(nullable = false, length = 50)
|
@Column(nullable = false, length = 50)
|
||||||
private String firstName;
|
private String firstName;
|
||||||
|
|
||||||
@@ -38,8 +41,9 @@ public class Customer {
|
|||||||
public Customer() {
|
public Customer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Customer(Long customerId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public Customer(Long customerId, Long userId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
this.customerId = customerId;
|
this.customerId = customerId;
|
||||||
|
this.userId = userId;
|
||||||
this.firstName = firstName;
|
this.firstName = firstName;
|
||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
@@ -56,6 +60,14 @@ public class Customer {
|
|||||||
this.customerId = customerId;
|
this.customerId = customerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
return firstName;
|
return firstName;
|
||||||
}
|
}
|
||||||
@@ -121,6 +133,7 @@ public class Customer {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Customer{" +
|
return "Customer{" +
|
||||||
"customerId=" + customerId +
|
"customerId=" + customerId +
|
||||||
|
", userId=" + userId +
|
||||||
", firstName='" + firstName + '\'' +
|
", firstName='" + firstName + '\'' +
|
||||||
", lastName='" + lastName + '\'' +
|
", lastName='" + lastName + '\'' +
|
||||||
", email='" + email + '\'' +
|
", email='" + email + '\'' +
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ public class Employee {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long employeeId;
|
private Long employeeId;
|
||||||
|
|
||||||
|
@Column(name = "user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
@Column(nullable = false, length = 50)
|
@Column(nullable = false, length = 50)
|
||||||
private String firstName;
|
private String firstName;
|
||||||
|
|
||||||
@@ -44,8 +47,9 @@ public class Employee {
|
|||||||
public Employee() {
|
public Employee() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Employee(Long employeeId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public Employee(Long employeeId, Long userId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
this.employeeId = employeeId;
|
this.employeeId = employeeId;
|
||||||
|
this.userId = userId;
|
||||||
this.firstName = firstName;
|
this.firstName = firstName;
|
||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
@@ -64,6 +68,14 @@ public class Employee {
|
|||||||
this.employeeId = employeeId;
|
this.employeeId = employeeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
return firstName;
|
return firstName;
|
||||||
}
|
}
|
||||||
@@ -145,6 +157,7 @@ public class Employee {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Employee{" +
|
return "Employee{" +
|
||||||
"employeeId=" + employeeId +
|
"employeeId=" + employeeId +
|
||||||
|
", userId=" + userId +
|
||||||
", firstName='" + firstName + '\'' +
|
", firstName='" + firstName + '\'' +
|
||||||
", lastName='" + lastName + '\'' +
|
", lastName='" + lastName + '\'' +
|
||||||
", email='" + email + '\'' +
|
", email='" + email + '\'' +
|
||||||
|
|||||||
91
src/main/java/com/petshop/backend/entity/Message.java
Normal file
91
src/main/java/com/petshop/backend/entity/Message.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package com.petshop.backend.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "message")
|
||||||
|
public class Message {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Long conversationId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Long senderId;
|
||||||
|
|
||||||
|
@Column(nullable = false, columnDefinition = "TEXT")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
private LocalDateTime timestamp;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean isRead = false;
|
||||||
|
|
||||||
|
public Message() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message(Long id, Long conversationId, Long senderId, String content, LocalDateTime timestamp, Boolean isRead) {
|
||||||
|
this.id = id;
|
||||||
|
this.conversationId = conversationId;
|
||||||
|
this.senderId = senderId;
|
||||||
|
this.content = content;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.isRead = isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getConversationId() {
|
||||||
|
return conversationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConversationId(Long conversationId) {
|
||||||
|
this.conversationId = conversationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSenderId() {
|
||||||
|
return senderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSenderId(Long senderId) {
|
||||||
|
this.senderId = senderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(LocalDateTime timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIsRead() {
|
||||||
|
return isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsRead(Boolean isRead) {
|
||||||
|
this.isRead = isRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,8 @@ public class Pet {
|
|||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long petId;
|
@Column(name = "petId")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
@Column(nullable = false, length = 50)
|
@Column(nullable = false, length = 50)
|
||||||
private String petName;
|
private String petName;
|
||||||
@@ -45,8 +46,8 @@ public class Pet {
|
|||||||
public Pet() {
|
public Pet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pet(Long petId, String petName, String petSpecies, String petBreed, Integer petAge, String petStatus, BigDecimal petPrice, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public Pet(Long id, String petName, String petSpecies, String petBreed, Integer petAge, String petStatus, BigDecimal petPrice, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
this.petId = petId;
|
this.id = id;
|
||||||
this.petName = petName;
|
this.petName = petName;
|
||||||
this.petSpecies = petSpecies;
|
this.petSpecies = petSpecies;
|
||||||
this.petBreed = petBreed;
|
this.petBreed = petBreed;
|
||||||
@@ -58,11 +59,11 @@ public class Pet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Long getPetId() {
|
public Long getPetId() {
|
||||||
return petId;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPetId(Long petId) {
|
public void setPetId(Long id) {
|
||||||
this.petId = petId;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPetName() {
|
public String getPetName() {
|
||||||
@@ -134,18 +135,18 @@ public class Pet {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Pet pet = (Pet) o;
|
Pet pet = (Pet) o;
|
||||||
return Objects.equals(petId, pet.petId);
|
return Objects.equals(id, pet.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(petId);
|
return Objects.hash(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Pet{" +
|
return "Pet{" +
|
||||||
"petId=" + petId +
|
"id=" + id +
|
||||||
", petName='" + petName + '\'' +
|
", petName='" + petName + '\'' +
|
||||||
", petSpecies='" + petSpecies + '\'' +
|
", petSpecies='" + petSpecies + '\'' +
|
||||||
", petBreed='" + petBreed + '\'' +
|
", petBreed='" + petBreed + '\'' +
|
||||||
|
|||||||
151
src/main/java/com/petshop/backend/entity/Refund.java
Normal file
151
src/main/java/com/petshop/backend/entity/Refund.java
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
package com.petshop.backend.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "refund")
|
||||||
|
public class Refund {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Long saleId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
@Column(nullable = false, precision = 10, scale = 2)
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Column(nullable = false, length = 500)
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(nullable = false, length = 20)
|
||||||
|
private RefundStatus status;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "created_at", updatable = false)
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updated_at")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public enum RefundStatus {
|
||||||
|
PENDING, APPROVED, REJECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
public Refund() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Refund(Long id, Long saleId, Long customerId, BigDecimal amount, String reason, RefundStatus status, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
|
this.id = id;
|
||||||
|
this.saleId = saleId;
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.amount = amount;
|
||||||
|
this.reason = reason;
|
||||||
|
this.status = status;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSaleId() {
|
||||||
|
return saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaleId(Long saleId) {
|
||||||
|
this.saleId = saleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(BigDecimal amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefundStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(RefundStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(LocalDateTime createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Refund refund = (Refund) o;
|
||||||
|
return Objects.equals(id, refund.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Refund{" +
|
||||||
|
"id=" + id +
|
||||||
|
", saleId=" + saleId +
|
||||||
|
", customerId=" + customerId +
|
||||||
|
", amount=" + amount +
|
||||||
|
", reason='" + reason + '\'' +
|
||||||
|
", status=" + status +
|
||||||
|
", createdAt=" + createdAt +
|
||||||
|
", updatedAt=" + updatedAt +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,10 @@ public class Sale {
|
|||||||
@JoinColumn(name = "storeId", nullable = false)
|
@JoinColumn(name = "storeId", nullable = false)
|
||||||
private StoreLocation store;
|
private StoreLocation store;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "customerId")
|
||||||
|
private Customer customer;
|
||||||
|
|
||||||
@Column(nullable = false, precision = 10, scale = 2)
|
@Column(nullable = false, precision = 10, scale = 2)
|
||||||
private BigDecimal totalAmount;
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
@@ -56,11 +60,12 @@ public class Sale {
|
|||||||
public Sale() {
|
public Sale() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sale(Long saleId, LocalDateTime saleDate, Employee employee, StoreLocation store, BigDecimal totalAmount, String paymentMethod, Boolean isRefund, Sale originalSale, List<SaleItem> items, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public Sale(Long saleId, LocalDateTime saleDate, Employee employee, StoreLocation store, Customer customer, BigDecimal totalAmount, String paymentMethod, Boolean isRefund, Sale originalSale, List<SaleItem> items, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
this.saleId = saleId;
|
this.saleId = saleId;
|
||||||
this.saleDate = saleDate;
|
this.saleDate = saleDate;
|
||||||
this.employee = employee;
|
this.employee = employee;
|
||||||
this.store = store;
|
this.store = store;
|
||||||
|
this.customer = customer;
|
||||||
this.totalAmount = totalAmount;
|
this.totalAmount = totalAmount;
|
||||||
this.paymentMethod = paymentMethod;
|
this.paymentMethod = paymentMethod;
|
||||||
this.isRefund = isRefund;
|
this.isRefund = isRefund;
|
||||||
@@ -102,6 +107,14 @@ public class Sale {
|
|||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Customer getCustomer() {
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomer(Customer customer) {
|
||||||
|
this.customer = customer;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalAmount() {
|
public BigDecimal getTotalAmount() {
|
||||||
return totalAmount;
|
return totalAmount;
|
||||||
}
|
}
|
||||||
@@ -178,6 +191,7 @@ public class Sale {
|
|||||||
", saleDate=" + saleDate +
|
", saleDate=" + saleDate +
|
||||||
", employee=" + employee +
|
", employee=" + employee +
|
||||||
", store=" + store +
|
", store=" + store +
|
||||||
|
", customer=" + customer +
|
||||||
", totalAmount=" + totalAmount +
|
", totalAmount=" + totalAmount +
|
||||||
", paymentMethod='" + paymentMethod + '\'' +
|
", paymentMethod='" + paymentMethod + '\'' +
|
||||||
", isRefund=" + isRefund +
|
", isRefund=" + isRefund +
|
||||||
|
|||||||
@@ -21,10 +21,22 @@ public class User {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@Column(unique = true, length = 100)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column(length = 100)
|
||||||
|
private String fullName;
|
||||||
|
|
||||||
|
@Column(length = 255)
|
||||||
|
private String avatarUrl;
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)")
|
@Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)")
|
||||||
private Role role;
|
private Role role;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean active = true;
|
||||||
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(name = "created_at", updatable = false)
|
@Column(name = "created_at", updatable = false)
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
@@ -34,17 +46,21 @@ public class User {
|
|||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
public enum Role {
|
public enum Role {
|
||||||
STAFF, ADMIN
|
CUSTOMER, STAFF, ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
public User() {
|
public User() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public User(Long id, String username, String password, Role role, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public User(Long id, String username, String password, String email, String fullName, String avatarUrl, Role role, Boolean active, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.email = email;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
this.role = role;
|
this.role = role;
|
||||||
|
this.active = active;
|
||||||
this.createdAt = createdAt;
|
this.createdAt = createdAt;
|
||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
}
|
}
|
||||||
@@ -73,6 +89,30 @@ public class User {
|
|||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatarUrl() {
|
||||||
|
return avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarUrl(String avatarUrl) {
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public Role getRole() {
|
public Role getRole() {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
@@ -81,6 +121,14 @@ public class User {
|
|||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(Boolean active) {
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
public LocalDateTime getCreatedAt() {
|
public LocalDateTime getCreatedAt() {
|
||||||
return createdAt;
|
return createdAt;
|
||||||
}
|
}
|
||||||
@@ -116,7 +164,11 @@ public class User {
|
|||||||
"id=" + id +
|
"id=" + id +
|
||||||
", username='" + username + '\'' +
|
", username='" + username + '\'' +
|
||||||
", password='" + password + '\'' +
|
", password='" + password + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
", avatarUrl='" + avatarUrl + '\'' +
|
||||||
", role=" + role +
|
", role=" + role +
|
||||||
|
", active=" + active +
|
||||||
", createdAt=" + createdAt +
|
", createdAt=" + createdAt +
|
||||||
", updatedAt=" + updatedAt +
|
", updatedAt=" + updatedAt +
|
||||||
'}';
|
'}';
|
||||||
|
|||||||
@@ -16,4 +16,12 @@ public interface AdoptionRepository extends JpaRepository<Adoption, Long> {
|
|||||||
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||||
Page<Adoption> searchAdoptions(@Param("q") String query, Pageable pageable);
|
Page<Adoption> searchAdoptions(@Param("q") String query, Pageable pageable);
|
||||||
|
|
||||||
|
Page<Adoption> findByCustomerCustomerId(Long customerId, Pageable pageable);
|
||||||
|
|
||||||
|
@Query("SELECT a FROM Adoption a WHERE a.customer.customerId = :customerId AND (" +
|
||||||
|
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%')))")
|
||||||
|
Page<Adoption> searchAdoptionsByCustomer(@Param("customerId") Long customerId, @Param("q") String query, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,4 +27,13 @@ public interface AppointmentRepository extends JpaRepository<Appointment, Long>
|
|||||||
"LOWER(a.service.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(a.service.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||||
Page<Appointment> searchAppointments(@Param("q") String query, Pageable pageable);
|
Page<Appointment> searchAppointments(@Param("q") String query, Pageable pageable);
|
||||||
|
|
||||||
|
Page<Appointment> findByCustomerCustomerId(Long customerId, Pageable pageable);
|
||||||
|
|
||||||
|
@Query("SELECT DISTINCT a FROM Appointment a LEFT JOIN a.pets p WHERE a.customer.customerId = :customerId AND (" +
|
||||||
|
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
"LOWER(a.service.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')))")
|
||||||
|
Page<Appointment> searchAppointmentsByCustomer(@Param("customerId") Long customerId, @Param("q") String query, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.petshop.backend.repository;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Conversation;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ConversationRepository extends JpaRepository<Conversation, Long> {
|
||||||
|
List<Conversation> findByCustomerId(Long customerId);
|
||||||
|
List<Conversation> findByStaffId(Long staffId);
|
||||||
|
}
|
||||||
@@ -8,9 +8,15 @@ import org.springframework.data.jpa.repository.Query;
|
|||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface CustomerRepository extends JpaRepository<Customer, Long> {
|
public interface CustomerRepository extends JpaRepository<Customer, Long> {
|
||||||
|
|
||||||
|
Optional<Customer> findByUserId(Long userId);
|
||||||
|
List<Customer> findAllByEmail(String email);
|
||||||
|
|
||||||
@Query("SELECT c FROM Customer c WHERE " +
|
@Query("SELECT c FROM Customer c WHERE " +
|
||||||
"LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import com.petshop.backend.entity.Employee;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
||||||
|
Optional<Employee> findByUserId(Long userId);
|
||||||
|
List<Employee> findAllByEmail(String email);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.petshop.backend.repository;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Message;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface MessageRepository extends JpaRepository<Message, Long> {
|
||||||
|
List<Message> findByConversationIdOrderByTimestampAsc(Long conversationId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.petshop.backend.repository;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Refund;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface RefundRepository extends JpaRepository<Refund, Long> {
|
||||||
|
List<Refund> findByCustomerId(Long customerId);
|
||||||
|
List<Refund> findBySaleId(Long saleId);
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import java.util.Optional;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface UserRepository extends JpaRepository<User, Long> {
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
Optional<User> findByUsername(String username);
|
Optional<User> findByUsername(String username);
|
||||||
|
Optional<User> findByEmail(String email);
|
||||||
boolean existsByUsername(String username);
|
boolean existsByUsername(String username);
|
||||||
|
|
||||||
@Query("SELECT u FROM User u WHERE " +
|
@Query("SELECT u FROM User u WHERE " +
|
||||||
|
|||||||
@@ -36,15 +36,14 @@ public class SecurityConfig {
|
|||||||
http
|
http
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers("/api/v1/auth/login").permitAll()
|
.requestMatchers("/api/v1/auth/login", "/api/v1/auth/register").permitAll()
|
||||||
|
.requestMatchers("/api/v1/health").permitAll()
|
||||||
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll()
|
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll()
|
||||||
.requestMatchers(HttpMethod.GET, "/api/v1/dropdowns/suppliers").hasRole("ADMIN")
|
.requestMatchers(HttpMethod.GET, "/api/v1/pets/**").permitAll()
|
||||||
.requestMatchers("/api/v1/inventory/**").hasRole("ADMIN")
|
.requestMatchers(HttpMethod.GET, "/api/v1/products/**").permitAll()
|
||||||
.requestMatchers("/api/v1/suppliers/**").hasRole("ADMIN")
|
.requestMatchers(HttpMethod.GET, "/api/v1/sales/**").permitAll()
|
||||||
.requestMatchers("/api/v1/product-suppliers/**").hasRole("ADMIN")
|
.requestMatchers(HttpMethod.GET, "/api/v1/services/**").permitAll()
|
||||||
.requestMatchers("/api/v1/purchase-orders/**").hasRole("ADMIN")
|
.requestMatchers(HttpMethod.GET, "/api/v1/categories/**").permitAll()
|
||||||
.requestMatchers("/api/v1/users/**").hasRole("ADMIN")
|
|
||||||
.requestMatchers("/api/v1/analytics/**").hasRole("ADMIN")
|
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
|||||||
@@ -28,19 +28,34 @@ public class AdoptionService {
|
|||||||
this.customerRepository = customerRepository;
|
this.customerRepository = customerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<AdoptionResponse> getAllAdoptions(String query, Pageable pageable) {
|
public Page<AdoptionResponse> getAllAdoptions(String query, Pageable pageable, Long customerId) {
|
||||||
Page<Adoption> adoptions;
|
Page<Adoption> adoptions;
|
||||||
|
|
||||||
|
if (customerId != null) {
|
||||||
|
if (query != null && !query.trim().isEmpty()) {
|
||||||
|
adoptions = adoptionRepository.searchAdoptionsByCustomer(customerId, query, pageable);
|
||||||
|
} else {
|
||||||
|
adoptions = adoptionRepository.findByCustomerCustomerId(customerId, pageable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (query != null && !query.trim().isEmpty()) {
|
if (query != null && !query.trim().isEmpty()) {
|
||||||
adoptions = adoptionRepository.searchAdoptions(query, pageable);
|
adoptions = adoptionRepository.searchAdoptions(query, pageable);
|
||||||
} else {
|
} else {
|
||||||
adoptions = adoptionRepository.findAll(pageable);
|
adoptions = adoptionRepository.findAll(pageable);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return adoptions.map(this::mapToResponse);
|
return adoptions.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdoptionResponse getAdoptionById(Long id) {
|
public AdoptionResponse getAdoptionById(Long id, Long customerId) {
|
||||||
Adoption adoption = adoptionRepository.findById(id)
|
Adoption adoption = adoptionRepository.findById(id)
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Adoption not found with id: " + id));
|
.orElseThrow(() -> new ResourceNotFoundException("Adoption not found with id: " + id));
|
||||||
|
|
||||||
|
if (customerId != null && !adoption.getCustomer().getCustomerId().equals(customerId)) {
|
||||||
|
throw new ResourceNotFoundException("You can only view your own adoptions");
|
||||||
|
}
|
||||||
|
|
||||||
return mapToResponse(adoption);
|
return mapToResponse(adoption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,19 +39,34 @@ public class AppointmentService {
|
|||||||
this.petRepository = petRepository;
|
this.petRepository = petRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<AppointmentResponse> getAllAppointments(String query, Pageable pageable) {
|
public Page<AppointmentResponse> getAllAppointments(String query, Pageable pageable, Long customerId) {
|
||||||
Page<Appointment> appointments;
|
Page<Appointment> appointments;
|
||||||
|
|
||||||
|
if (customerId != null) {
|
||||||
|
if (query != null && !query.trim().isEmpty()) {
|
||||||
|
appointments = appointmentRepository.searchAppointmentsByCustomer(customerId, query, pageable);
|
||||||
|
} else {
|
||||||
|
appointments = appointmentRepository.findByCustomerCustomerId(customerId, pageable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (query != null && !query.trim().isEmpty()) {
|
if (query != null && !query.trim().isEmpty()) {
|
||||||
appointments = appointmentRepository.searchAppointments(query, pageable);
|
appointments = appointmentRepository.searchAppointments(query, pageable);
|
||||||
} else {
|
} else {
|
||||||
appointments = appointmentRepository.findAll(pageable);
|
appointments = appointmentRepository.findAll(pageable);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return appointments.map(this::mapToResponse);
|
return appointments.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppointmentResponse getAppointmentById(Long id) {
|
public AppointmentResponse getAppointmentById(Long id, Long customerId) {
|
||||||
Appointment appointment = appointmentRepository.findById(id)
|
Appointment appointment = appointmentRepository.findById(id)
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Appointment not found with id: " + id));
|
.orElseThrow(() -> new ResourceNotFoundException("Appointment not found with id: " + id));
|
||||||
|
|
||||||
|
if (customerId != null && !appointment.getCustomer().getCustomerId().equals(customerId)) {
|
||||||
|
throw new ResourceNotFoundException("You can only view your own appointments");
|
||||||
|
}
|
||||||
|
|
||||||
return mapToResponse(appointment);
|
return mapToResponse(appointment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
144
src/main/java/com/petshop/backend/service/ChatService.java
Normal file
144
src/main/java/com/petshop/backend/service/ChatService.java
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package com.petshop.backend.service;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.chat.ConversationRequest;
|
||||||
|
import com.petshop.backend.dto.chat.ConversationResponse;
|
||||||
|
import com.petshop.backend.dto.chat.MessageRequest;
|
||||||
|
import com.petshop.backend.dto.chat.MessageResponse;
|
||||||
|
import com.petshop.backend.entity.Conversation;
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.entity.Message;
|
||||||
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
|
import com.petshop.backend.repository.ConversationRepository;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.MessageRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ChatService {
|
||||||
|
|
||||||
|
private final ConversationRepository conversationRepository;
|
||||||
|
private final MessageRepository messageRepository;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
public ChatService(ConversationRepository conversationRepository,
|
||||||
|
MessageRepository messageRepository,
|
||||||
|
UserRepository userRepository,
|
||||||
|
CustomerRepository customerRepository) {
|
||||||
|
this.conversationRepository = conversationRepository;
|
||||||
|
this.messageRepository = messageRepository;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public ConversationResponse createConversation(Long userId, ConversationRequest request) {
|
||||||
|
User user = userRepository.findById(userId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("User not found"));
|
||||||
|
|
||||||
|
Customer customer = customerRepository.findByUserId(userId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
|
||||||
|
|
||||||
|
Conversation conversation = new Conversation();
|
||||||
|
conversation.setCustomerId(customer.getCustomerId());
|
||||||
|
conversation.setStatus(Conversation.ConversationStatus.OPEN);
|
||||||
|
conversation = conversationRepository.save(conversation);
|
||||||
|
|
||||||
|
Message message = new Message();
|
||||||
|
message.setConversationId(conversation.getId());
|
||||||
|
message.setSenderId(userId);
|
||||||
|
message.setContent(request.getMessage());
|
||||||
|
message.setIsRead(false);
|
||||||
|
messageRepository.save(message);
|
||||||
|
|
||||||
|
return ConversationResponse.fromEntity(conversation, request.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ConversationResponse> getConversations(Long userId, User.Role role) {
|
||||||
|
List<Conversation> conversations;
|
||||||
|
|
||||||
|
if (role == User.Role.CUSTOMER) {
|
||||||
|
Customer customer = customerRepository.findByUserId(userId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
|
||||||
|
conversations = conversationRepository.findByCustomerId(customer.getCustomerId());
|
||||||
|
} else if (role == User.Role.STAFF) {
|
||||||
|
conversations = conversationRepository.findByStaffId(userId);
|
||||||
|
if (conversations.isEmpty()) {
|
||||||
|
conversations = conversationRepository.findAll();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conversations = conversationRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return conversations.stream()
|
||||||
|
.map(conv -> {
|
||||||
|
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conv.getId());
|
||||||
|
String lastMessage = messages.isEmpty() ? "" : messages.get(messages.size() - 1).getContent();
|
||||||
|
return ConversationResponse.fromEntity(conv, lastMessage);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConversationResponse getConversation(Long conversationId, Long userId, User.Role role) {
|
||||||
|
Conversation conversation = conversationRepository.findById(conversationId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
|
||||||
|
|
||||||
|
if (role == User.Role.CUSTOMER) {
|
||||||
|
Customer customer = customerRepository.findByUserId(userId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
|
||||||
|
if (!conversation.getCustomerId().equals(customer.getCustomerId())) {
|
||||||
|
throw new AccessDeniedException("You can only view your own conversations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
|
||||||
|
String lastMessage = messages.isEmpty() ? "" : messages.get(messages.size() - 1).getContent();
|
||||||
|
|
||||||
|
return ConversationResponse.fromEntity(conversation, lastMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public MessageResponse sendMessage(Long conversationId, Long userId, User.Role role, MessageRequest request) {
|
||||||
|
Conversation conversation = conversationRepository.findById(conversationId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
|
||||||
|
|
||||||
|
Message message = new Message();
|
||||||
|
message.setConversationId(conversationId);
|
||||||
|
message.setSenderId(userId);
|
||||||
|
message.setContent(request.getContent());
|
||||||
|
message.setIsRead(false);
|
||||||
|
message = messageRepository.save(message);
|
||||||
|
|
||||||
|
if (role == User.Role.STAFF && conversation.getStaffId() == null) {
|
||||||
|
conversation.setStaffId(userId);
|
||||||
|
conversationRepository.save(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MessageResponse.fromEntity(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MessageResponse> getMessages(Long conversationId, Long userId, User.Role role) {
|
||||||
|
Conversation conversation = conversationRepository.findById(conversationId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
|
||||||
|
|
||||||
|
if (role == User.Role.CUSTOMER) {
|
||||||
|
Customer customer = customerRepository.findByUserId(userId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
|
||||||
|
if (!conversation.getCustomerId().equals(customer.getCustomerId())) {
|
||||||
|
throw new AccessDeniedException("You can only view messages from your own conversations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
|
||||||
|
return messages.stream()
|
||||||
|
.map(MessageResponse::fromEntity)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
111
src/main/java/com/petshop/backend/service/RefundService.java
Normal file
111
src/main/java/com/petshop/backend/service/RefundService.java
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package com.petshop.backend.service;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.refund.RefundRequest;
|
||||||
|
import com.petshop.backend.dto.refund.RefundResponse;
|
||||||
|
import com.petshop.backend.entity.Refund;
|
||||||
|
import com.petshop.backend.entity.Sale;
|
||||||
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.repository.RefundRepository;
|
||||||
|
import com.petshop.backend.repository.SaleRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RefundService {
|
||||||
|
|
||||||
|
private final RefundRepository refundRepository;
|
||||||
|
private final SaleRepository saleRepository;
|
||||||
|
|
||||||
|
public RefundService(RefundRepository refundRepository, SaleRepository saleRepository) {
|
||||||
|
this.refundRepository = refundRepository;
|
||||||
|
this.saleRepository = saleRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public RefundResponse createRefund(RefundRequest request, Long customerId) {
|
||||||
|
Sale sale = saleRepository.findById(request.getSaleId())
|
||||||
|
.orElseThrow(() -> new RuntimeException("Sale not found"));
|
||||||
|
|
||||||
|
if (sale.getCustomer() == null) {
|
||||||
|
throw new RuntimeException("Sale has no associated customer");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customerId != null && !sale.getCustomer().getCustomerId().equals(customerId)) {
|
||||||
|
throw new RuntimeException("You can only create refunds for your own purchases");
|
||||||
|
}
|
||||||
|
|
||||||
|
Refund refund = new Refund();
|
||||||
|
refund.setSaleId(sale.getSaleId());
|
||||||
|
refund.setCustomerId(sale.getCustomer().getCustomerId());
|
||||||
|
refund.setAmount(sale.getTotalAmount());
|
||||||
|
refund.setReason(request.getReason());
|
||||||
|
refund.setStatus(Refund.RefundStatus.PENDING);
|
||||||
|
|
||||||
|
Refund savedRefund = refundRepository.save(refund);
|
||||||
|
return toResponse(savedRefund);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefundResponse getRefundById(Long id, Long customerId) {
|
||||||
|
Refund refund = refundRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Refund not found"));
|
||||||
|
|
||||||
|
if (customerId != null && !refund.getCustomerId().equals(customerId)) {
|
||||||
|
throw new RuntimeException("You can only view your own refunds");
|
||||||
|
}
|
||||||
|
|
||||||
|
return toResponse(refund);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RefundResponse> getAllRefunds(Long customerId) {
|
||||||
|
List<Refund> refunds;
|
||||||
|
|
||||||
|
if (customerId != null) {
|
||||||
|
refunds = refundRepository.findByCustomerId(customerId);
|
||||||
|
} else {
|
||||||
|
refunds = refundRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return refunds.stream()
|
||||||
|
.map(this::toResponse)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public RefundResponse updateRefundStatus(Long id, String status) {
|
||||||
|
Refund refund = refundRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Refund not found"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
refund.setStatus(Refund.RefundStatus.valueOf(status.toUpperCase()));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new RuntimeException("Invalid status: " + status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Refund updatedRefund = refundRepository.save(refund);
|
||||||
|
return toResponse(updatedRefund);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteRefund(Long id) {
|
||||||
|
if (!refundRepository.existsById(id)) {
|
||||||
|
throw new RuntimeException("Refund not found");
|
||||||
|
}
|
||||||
|
refundRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RefundResponse toResponse(Refund refund) {
|
||||||
|
return new RefundResponse(
|
||||||
|
refund.getId(),
|
||||||
|
refund.getSaleId(),
|
||||||
|
refund.getCustomerId(),
|
||||||
|
refund.getAmount(),
|
||||||
|
refund.getReason(),
|
||||||
|
refund.getStatus().name(),
|
||||||
|
refund.getCreatedAt(),
|
||||||
|
refund.getUpdatedAt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.petshop.backend.entity.*;
|
|||||||
import com.petshop.backend.exception.BusinessException;
|
import com.petshop.backend.exception.BusinessException;
|
||||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
import com.petshop.backend.repository.*;
|
import com.petshop.backend.repository.*;
|
||||||
|
import com.petshop.backend.util.AuthenticationHelper;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@@ -25,13 +26,17 @@ public class SaleService {
|
|||||||
private final StoreRepository storeRepository;
|
private final StoreRepository storeRepository;
|
||||||
private final InventoryRepository inventoryRepository;
|
private final InventoryRepository inventoryRepository;
|
||||||
private final EmployeeRepository employeeRepository;
|
private final EmployeeRepository employeeRepository;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, EmployeeRepository employeeRepository) {
|
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, EmployeeRepository employeeRepository, UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
this.saleRepository = saleRepository;
|
this.saleRepository = saleRepository;
|
||||||
this.productRepository = productRepository;
|
this.productRepository = productRepository;
|
||||||
this.storeRepository = storeRepository;
|
this.storeRepository = storeRepository;
|
||||||
this.inventoryRepository = inventoryRepository;
|
this.inventoryRepository = inventoryRepository;
|
||||||
this.employeeRepository = employeeRepository;
|
this.employeeRepository = employeeRepository;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<SaleResponse> getAllSales(String query, Pageable pageable) {
|
public Page<SaleResponse> getAllSales(String query, Pageable pageable) {
|
||||||
@@ -52,9 +57,7 @@ public class SaleService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public SaleResponse createSale(SaleRequest request) {
|
public SaleResponse createSale(SaleRequest request) {
|
||||||
Employee employee = employeeRepository.findAll().stream()
|
Employee employee = AuthenticationHelper.getAuthenticatedEmployee(userRepository, employeeRepository);
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("No employees found"));
|
|
||||||
|
|
||||||
StoreLocation store = storeRepository.findById(request.getStoreId())
|
StoreLocation store = storeRepository.findById(request.getStoreId())
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()));
|
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()));
|
||||||
@@ -66,6 +69,12 @@ public class SaleService {
|
|||||||
sale.setPaymentMethod(request.getPaymentMethod());
|
sale.setPaymentMethod(request.getPaymentMethod());
|
||||||
sale.setIsRefund(request.getIsRefund() != null ? request.getIsRefund() : false);
|
sale.setIsRefund(request.getIsRefund() != null ? request.getIsRefund() : false);
|
||||||
|
|
||||||
|
if (request.getCustomerId() != null) {
|
||||||
|
Customer customer = customerRepository.findById(request.getCustomerId())
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer not found with id: " + request.getCustomerId()));
|
||||||
|
sale.setCustomer(customer);
|
||||||
|
}
|
||||||
|
|
||||||
if (sale.getIsRefund() && request.getOriginalSaleId() != null) {
|
if (sale.getIsRefund() && request.getOriginalSaleId() != null) {
|
||||||
Sale originalSale = saleRepository.findById(request.getOriginalSaleId())
|
Sale originalSale = saleRepository.findById(request.getOriginalSaleId())
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Original sale not found with id: " + request.getOriginalSaleId()));
|
.orElseThrow(() -> new ResourceNotFoundException("Original sale not found with id: " + request.getOriginalSaleId()));
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
package com.petshop.backend.service;
|
package com.petshop.backend.service;
|
||||||
|
|
||||||
|
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||||
|
import com.petshop.backend.dto.store.StoreRequest;
|
||||||
import com.petshop.backend.dto.store.StoreResponse;
|
import com.petshop.backend.dto.store.StoreResponse;
|
||||||
import com.petshop.backend.entity.StoreLocation;
|
import com.petshop.backend.entity.StoreLocation;
|
||||||
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
import com.petshop.backend.repository.StoreRepository;
|
import com.petshop.backend.repository.StoreRepository;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class StoreService {
|
public class StoreService {
|
||||||
@@ -26,6 +30,51 @@ public class StoreService {
|
|||||||
return stores.map(this::mapToResponse);
|
return stores.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StoreResponse getStoreById(Long id) {
|
||||||
|
StoreLocation store = storeRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + id));
|
||||||
|
return mapToResponse(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public StoreResponse createStore(StoreRequest request) {
|
||||||
|
StoreLocation store = new StoreLocation();
|
||||||
|
store.setStoreName(request.getStoreName());
|
||||||
|
store.setAddress(request.getAddress());
|
||||||
|
store.setPhone(request.getPhone());
|
||||||
|
store.setEmail(request.getEmail());
|
||||||
|
|
||||||
|
store = storeRepository.save(store);
|
||||||
|
return mapToResponse(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public StoreResponse updateStore(Long id, StoreRequest request) {
|
||||||
|
StoreLocation store = storeRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + id));
|
||||||
|
|
||||||
|
store.setStoreName(request.getStoreName());
|
||||||
|
store.setAddress(request.getAddress());
|
||||||
|
store.setPhone(request.getPhone());
|
||||||
|
store.setEmail(request.getEmail());
|
||||||
|
|
||||||
|
store = storeRepository.save(store);
|
||||||
|
return mapToResponse(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteStore(Long id) {
|
||||||
|
if (!storeRepository.existsById(id)) {
|
||||||
|
throw new ResourceNotFoundException("Store not found with id: " + id);
|
||||||
|
}
|
||||||
|
storeRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void bulkDeleteStores(BulkDeleteRequest request) {
|
||||||
|
storeRepository.deleteAllById(request.getIds());
|
||||||
|
}
|
||||||
|
|
||||||
private StoreResponse mapToResponse(StoreLocation store) {
|
private StoreResponse mapToResponse(StoreLocation store) {
|
||||||
return new StoreResponse(
|
return new StoreResponse(
|
||||||
store.getStoreId(),
|
store.getStoreId(),
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package com.petshop.backend.service;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.entity.Employee;
|
||||||
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.EmployeeRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserBusinessLinkageService {
|
||||||
|
|
||||||
|
private final EmployeeRepository employeeRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UserBusinessLinkageService(EmployeeRepository employeeRepository, CustomerRepository customerRepository) {
|
||||||
|
this.employeeRepository = employeeRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Employee ensureLinkedEmployee(User user) {
|
||||||
|
// Check if already linked
|
||||||
|
if (user.getId() != null) {
|
||||||
|
var existing = employeeRepository.findByUserId(user.getId());
|
||||||
|
if (existing.isPresent()) {
|
||||||
|
return existing.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for email matches
|
||||||
|
List<Employee> emailMatches = employeeRepository.findAllByEmail(user.getEmail());
|
||||||
|
|
||||||
|
// If exactly one match exists and has no userId, link it
|
||||||
|
if (emailMatches.size() == 1) {
|
||||||
|
Employee employee = emailMatches.get(0);
|
||||||
|
if (employee.getUserId() == null) {
|
||||||
|
employee.setUserId(user.getId());
|
||||||
|
return employeeRepository.save(employee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise create a new linked Employee
|
||||||
|
Employee newEmployee = new Employee();
|
||||||
|
newEmployee.setUserId(user.getId());
|
||||||
|
newEmployee.setEmail(user.getEmail());
|
||||||
|
|
||||||
|
// Split fullName into firstName and lastName
|
||||||
|
String[] nameParts = splitFullName(user.getFullName());
|
||||||
|
newEmployee.setFirstName(nameParts[0]);
|
||||||
|
newEmployee.setLastName(nameParts[1]);
|
||||||
|
|
||||||
|
// Set required fields with deterministic values
|
||||||
|
newEmployee.setPhone("000-000-0000");
|
||||||
|
newEmployee.setIsActive(true);
|
||||||
|
|
||||||
|
// Map role based on user role
|
||||||
|
if (user.getRole() == User.Role.ADMIN) {
|
||||||
|
newEmployee.setRole("Manager");
|
||||||
|
} else if (user.getRole() == User.Role.STAFF) {
|
||||||
|
newEmployee.setRole("Staff");
|
||||||
|
} else {
|
||||||
|
newEmployee.setRole("Staff"); // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
return employeeRepository.save(newEmployee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Customer ensureLinkedCustomer(User user) {
|
||||||
|
// Check if already linked
|
||||||
|
if (user.getId() != null) {
|
||||||
|
var existing = customerRepository.findByUserId(user.getId());
|
||||||
|
if (existing.isPresent()) {
|
||||||
|
return existing.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for email matches
|
||||||
|
List<Customer> emailMatches = customerRepository.findAllByEmail(user.getEmail());
|
||||||
|
|
||||||
|
// If exactly one match exists and has no userId, link it
|
||||||
|
if (emailMatches.size() == 1) {
|
||||||
|
Customer customer = emailMatches.get(0);
|
||||||
|
if (customer.getUserId() == null) {
|
||||||
|
customer.setUserId(user.getId());
|
||||||
|
return customerRepository.save(customer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise create a new linked Customer
|
||||||
|
Customer newCustomer = new Customer();
|
||||||
|
newCustomer.setUserId(user.getId());
|
||||||
|
newCustomer.setEmail(user.getEmail());
|
||||||
|
|
||||||
|
// Split fullName into firstName and lastName
|
||||||
|
String[] nameParts = splitFullName(user.getFullName());
|
||||||
|
newCustomer.setFirstName(nameParts[0]);
|
||||||
|
newCustomer.setLastName(nameParts[1]);
|
||||||
|
|
||||||
|
// Set required fields with deterministic values
|
||||||
|
newCustomer.setPhone("000-000-0001");
|
||||||
|
|
||||||
|
return customerRepository.save(newCustomer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitFullName(String fullName) {
|
||||||
|
if (fullName == null || fullName.trim().isEmpty()) {
|
||||||
|
return new String[]{"System", "User"};
|
||||||
|
}
|
||||||
|
|
||||||
|
String trimmed = fullName.trim();
|
||||||
|
int spaceIndex = trimmed.indexOf(' ');
|
||||||
|
|
||||||
|
if (spaceIndex == -1) {
|
||||||
|
// Single token
|
||||||
|
return new String[]{trimmed, "User"};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple tokens
|
||||||
|
String firstName = trimmed.substring(0, spaceIndex).trim();
|
||||||
|
String lastName = trimmed.substring(spaceIndex + 1).trim();
|
||||||
|
|
||||||
|
if (firstName.isEmpty()) {
|
||||||
|
firstName = "System";
|
||||||
|
}
|
||||||
|
if (lastName.isEmpty()) {
|
||||||
|
lastName = "User";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[]{firstName, lastName};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,10 +17,12 @@ public class UserService {
|
|||||||
|
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final UserBusinessLinkageService userBusinessLinkageService;
|
||||||
|
|
||||||
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
|
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.userBusinessLinkageService = userBusinessLinkageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<UserResponse> getAllUsers(String query, Pageable pageable) {
|
public Page<UserResponse> getAllUsers(String query, Pageable pageable) {
|
||||||
@@ -44,9 +46,20 @@ public class UserService {
|
|||||||
User user = new User();
|
User user = new User();
|
||||||
user.setUsername(request.getUsername());
|
user.setUsername(request.getUsername());
|
||||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||||
|
user.setFullName(request.getFullName());
|
||||||
|
user.setEmail(request.getEmail());
|
||||||
user.setRole(request.getRole());
|
user.setRole(request.getRole());
|
||||||
|
user.setActive(request.getActive() != null ? request.getActive() : true);
|
||||||
|
|
||||||
user = userRepository.save(user);
|
user = userRepository.save(user);
|
||||||
|
|
||||||
|
// Create or link business entity based on role
|
||||||
|
if (user.getRole() == User.Role.STAFF || user.getRole() == User.Role.ADMIN) {
|
||||||
|
userBusinessLinkageService.ensureLinkedEmployee(user);
|
||||||
|
} else if (user.getRole() == User.Role.CUSTOMER) {
|
||||||
|
userBusinessLinkageService.ensureLinkedCustomer(user);
|
||||||
|
}
|
||||||
|
|
||||||
return mapToResponse(user);
|
return mapToResponse(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +72,10 @@ public class UserService {
|
|||||||
if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
|
if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
|
||||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||||
}
|
}
|
||||||
|
user.setFullName(request.getFullName());
|
||||||
|
user.setEmail(request.getEmail());
|
||||||
user.setRole(request.getRole());
|
user.setRole(request.getRole());
|
||||||
|
user.setActive(request.getActive() != null ? request.getActive() : true);
|
||||||
|
|
||||||
user = userRepository.save(user);
|
user = userRepository.save(user);
|
||||||
return mapToResponse(user);
|
return mapToResponse(user);
|
||||||
@@ -82,7 +98,12 @@ public class UserService {
|
|||||||
UserResponse response = new UserResponse();
|
UserResponse response = new UserResponse();
|
||||||
response.setId(user.getId());
|
response.setId(user.getId());
|
||||||
response.setUsername(user.getUsername());
|
response.setUsername(user.getUsername());
|
||||||
|
response.setFullName(user.getFullName());
|
||||||
|
response.setEmail(user.getEmail());
|
||||||
response.setRole(user.getRole().toString());
|
response.setRole(user.getRole().toString());
|
||||||
|
response.setActive(user.getActive());
|
||||||
|
response.setCreatedAt(user.getCreatedAt());
|
||||||
|
response.setUpdatedAt(user.getUpdatedAt());
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.petshop.backend.util;
|
||||||
|
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
|
import com.petshop.backend.entity.Employee;
|
||||||
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
|
import com.petshop.backend.repository.EmployeeRepository;
|
||||||
|
import com.petshop.backend.repository.UserRepository;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AuthenticationHelper {
|
||||||
|
|
||||||
|
public static User getAuthenticatedUser(UserRepository userRepository) {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
|
throw new RuntimeException("No authenticated user found");
|
||||||
|
}
|
||||||
|
|
||||||
|
String username = authentication.getName();
|
||||||
|
return userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new RuntimeException("User not found: " + username));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Employee getAuthenticatedEmployee(UserRepository userRepository, EmployeeRepository employeeRepository) {
|
||||||
|
User user = getAuthenticatedUser(userRepository);
|
||||||
|
return employeeRepository.findByUserId(user.getId())
|
||||||
|
.orElseThrow(() -> new RuntimeException("Employee record not found for user: " + user.getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Customer getAuthenticatedCustomer(UserRepository userRepository, CustomerRepository customerRepository) {
|
||||||
|
User user = getAuthenticatedUser(userRepository);
|
||||||
|
return customerRepository.findByUserId(user.getId())
|
||||||
|
.orElseThrow(() -> new RuntimeException("Customer record not found for user: " + user.getUsername()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,15 +2,25 @@ spring:
|
|||||||
application:
|
application:
|
||||||
name: petshop-backend
|
name: petshop-backend
|
||||||
|
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
enabled: true
|
||||||
|
max-file-size: 5MB
|
||||||
|
max-request-size: 5MB
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/Petstoredb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC}
|
url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/Petstoredb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC}
|
||||||
username: ${SPRING_DATASOURCE_USERNAME:petshop}
|
username: ${SPRING_DATASOURCE_USERNAME:petshop}
|
||||||
password: ${SPRING_DATASOURCE_PASSWORD:petshop}
|
password: ${SPRING_DATASOURCE_PASSWORD:petshop}
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
sql:
|
||||||
|
init:
|
||||||
|
mode: never
|
||||||
|
|
||||||
jpa:
|
jpa:
|
||||||
hibernate:
|
hibernate:
|
||||||
ddl-auto: validate
|
ddl-auto: none
|
||||||
naming:
|
naming:
|
||||||
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
||||||
show-sql: ${JPA_SHOW_SQL:false}
|
show-sql: ${JPA_SHOW_SQL:false}
|
||||||
|
|||||||
205
src/main/resources/data.sql
Normal file
205
src/main/resources/data.sql
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
-- Insert Sample Data
|
||||||
|
|
||||||
|
INSERT INTO storeLocation (storeName, address, phone, email)
|
||||||
|
VALUES
|
||||||
|
('Downtown Branch', '123 Main St', '123-456-7890', 'downtown@petshop.com'),
|
||||||
|
('North Branch', '456 North Ave', '987-654-3210', 'north@petshop.com'),
|
||||||
|
('West Side Store', '789 West Blvd', '555-123-4567', 'westside@petshop.com'),
|
||||||
|
('East End Shop', '321 East Road', '555-987-6543', 'eastend@petshop.com'),
|
||||||
|
('South Mall Location', '654 South Plaza', '555-246-8135', 'southmall@petshop.com');
|
||||||
|
|
||||||
|
INSERT INTO employee (firstName, lastName, email, phone, role, isActive)
|
||||||
|
VALUES
|
||||||
|
('John', 'Doe', 'john@petshop.com', '111-222-3333', 'Manager', TRUE),
|
||||||
|
('Sara', 'Smith', 'sara@petshop.com', '444-555-6666', 'Staff', TRUE),
|
||||||
|
('Michael', 'Johnson', 'michael@petshop.com', '222-333-4444', 'Groomer', TRUE),
|
||||||
|
('Lisa', 'Williams', 'lisa@petshop.com', '333-444-5555', 'Staff', TRUE),
|
||||||
|
('David', 'Brown', 'david@petshop.com', '555-666-7777', 'Veterinarian', TRUE),
|
||||||
|
('Emma', 'Davis', 'emma@petshop.com', '666-777-8888', 'Manager', FALSE);
|
||||||
|
|
||||||
|
INSERT INTO employeeStore (employeeId, storeId)
|
||||||
|
VALUES
|
||||||
|
(1, 1),
|
||||||
|
(2, 1),
|
||||||
|
(2, 2),
|
||||||
|
(3, 2),
|
||||||
|
(4, 3),
|
||||||
|
(5, 1),
|
||||||
|
(5, 4),
|
||||||
|
(6, 5);
|
||||||
|
|
||||||
|
INSERT INTO customer (firstName, lastName, email, phone)
|
||||||
|
VALUES
|
||||||
|
('Alex', 'Brown', 'alex@gmail.com', '777-888-9999'),
|
||||||
|
('Emily', 'Clark', 'emily@gmail.com', '666-555-4444'),
|
||||||
|
('James', 'Wilson', 'james@gmail.com', '888-999-0000'),
|
||||||
|
('Olivia', 'Martinez', 'olivia@gmail.com', '999-000-1111'),
|
||||||
|
('William', 'Anderson', 'william@gmail.com', '000-111-2222'),
|
||||||
|
('Sophia', 'Taylor', 'sophia@gmail.com', '111-222-3333');
|
||||||
|
|
||||||
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice)
|
||||||
|
VALUES
|
||||||
|
('Buddy', 'Dog', 'Labrador', 2, 'Available', 500.00),
|
||||||
|
('Milo', 'Cat', 'Persian', 1, 'Available', 300.00),
|
||||||
|
('Charlie', 'Dog', 'Golden Retriever', 3, 'Available', 550.00),
|
||||||
|
('Luna', 'Cat', 'Siamese', 2, 'Adopted', 350.00),
|
||||||
|
('Max', 'Dog', 'Beagle', 1, 'Available', 450.00),
|
||||||
|
('Bella', 'Cat', 'Maine Coon', 4, 'Available', 400.00);
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus)
|
||||||
|
VALUES
|
||||||
|
(1, 1, '2026-01-15', 'Completed'),
|
||||||
|
(4, 3, '2026-01-20', 'Completed'),
|
||||||
|
(2, 2, '2026-01-25', 'Pending'),
|
||||||
|
(5, 4, '2026-02-01', 'Completed'),
|
||||||
|
(6, 5, '2026-02-02', 'Pending');
|
||||||
|
|
||||||
|
INSERT INTO supplier (supCompany, supContactFirstName, supContactLastName, supEmail, supPhone)
|
||||||
|
VALUES
|
||||||
|
('PetFood Inc', 'Robert', 'King', 'contact@petfood.com', '888-111-2222'),
|
||||||
|
('Toy World', 'Jennifer', 'Lee', 'sales@toyworld.com', '888-222-3333'),
|
||||||
|
('Pet Supplies Co', 'Kevin', 'White', 'info@petsupplies.com', '888-333-4444'),
|
||||||
|
('Animal Care Products', 'Nancy', 'Green', 'orders@animalcare.com', '888-444-5555'),
|
||||||
|
('Premium Pet Goods', 'Tom', 'Black', 'support@premiumpet.com', '888-555-6666');
|
||||||
|
|
||||||
|
INSERT INTO category (categoryName, categoryType)
|
||||||
|
VALUES
|
||||||
|
('Dog Food', 'Product'),
|
||||||
|
('Cat Toys', 'Product'),
|
||||||
|
('Bird Supplies', 'Product'),
|
||||||
|
('Aquarium', 'Product'),
|
||||||
|
('Small Animals', 'Product');
|
||||||
|
|
||||||
|
INSERT INTO product (prodName, prodPrice, categoryId, prodDesc)
|
||||||
|
VALUES
|
||||||
|
('Premium Dog Food', 50.00, 1, 'High quality dog food'),
|
||||||
|
('Cat Toy Ball', 10.00, 2, 'Colorful toy for cats'),
|
||||||
|
('Bird Cage Large', 120.00, 3, 'Spacious bird cage'),
|
||||||
|
('Fish Tank 20 Gallon', 80.00, 4, 'Complete aquarium kit'),
|
||||||
|
('Hamster Wheel', 15.00, 5, 'Exercise wheel for small pets'),
|
||||||
|
('Organic Dog Treats', 25.00, 1, 'Natural dog treats');
|
||||||
|
|
||||||
|
INSERT INTO productSupplier (supId, prodId, cost)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 35.00),
|
||||||
|
(1, 2, 6.50),
|
||||||
|
(2, 2, 7.00),
|
||||||
|
(3, 3, 90.00),
|
||||||
|
(3, 4, 60.00),
|
||||||
|
(4, 5, 10.00),
|
||||||
|
(5, 6, 18.00),
|
||||||
|
(1, 6, 17.50);
|
||||||
|
|
||||||
|
INSERT INTO inventory (prodId, quantity)
|
||||||
|
VALUES
|
||||||
|
(1, 100),
|
||||||
|
(2, 200),
|
||||||
|
(3, 50),
|
||||||
|
(4, 30),
|
||||||
|
(5, 150),
|
||||||
|
(6, 75);
|
||||||
|
|
||||||
|
INSERT INTO service (serviceName, serviceDesc, serviceDuration, servicePrice)
|
||||||
|
VALUES
|
||||||
|
('Pet Grooming', 'Full grooming service', 60, 40.00),
|
||||||
|
('Nail Trimming', 'Quick nail trim', 15, 10.00),
|
||||||
|
('Bath and Brush', 'Bathing and brushing service', 45, 30.00),
|
||||||
|
('Veterinary Checkup', 'Complete health examination', 30, 75.00),
|
||||||
|
('Teeth Cleaning', 'Professional dental cleaning', 90, 100.00);
|
||||||
|
|
||||||
|
INSERT INTO appointment (serviceId, customerId, appointmentDate, appointmentTime, appointmentStatus)
|
||||||
|
VALUES
|
||||||
|
(1, 2, '2026-02-01', '10:30:00', 'Booked'),
|
||||||
|
(2, 1, '2026-02-03', '14:00:00', 'Booked'),
|
||||||
|
(3, 3, '2026-02-05', '09:00:00', 'Completed'),
|
||||||
|
(4, 4, '2026-02-07', '11:30:00', 'Booked'),
|
||||||
|
(5, 5, '2026-02-10', '15:00:00', 'Cancelled');
|
||||||
|
|
||||||
|
INSERT INTO appointmentPet (appointmentId, petId)
|
||||||
|
VALUES
|
||||||
|
(1, 2),
|
||||||
|
(2, 1),
|
||||||
|
(3, 3),
|
||||||
|
(4, 5),
|
||||||
|
(5, 6);
|
||||||
|
|
||||||
|
INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId, customerId)
|
||||||
|
VALUES
|
||||||
|
('2026-01-05 09:15:00', 125.00, 'Card', 1, 1, 1),
|
||||||
|
('2026-01-08 11:30:00', 200.00, 'Card', 2, 1, 2),
|
||||||
|
('2026-01-12 14:20:00', 60.00, 'Cash', 3, 2, 3),
|
||||||
|
('2026-01-15 10:45:00', 150.00, 'Debit', 1, 1, 1),
|
||||||
|
('2026-01-18 16:30:00', 80.00, 'Card', 4, 3, 2),
|
||||||
|
('2026-01-22 13:15:00', 95.00, 'Cash', 2, 2, NULL),
|
||||||
|
('2026-01-25 15:40:00', 240.00, 'Card', 5, 4, 4),
|
||||||
|
('2026-01-28 10:30:00', 80.00, 'Cash', 1, 1, NULL),
|
||||||
|
('2026-02-01 09:00:00', 175.00, 'Card', 3, 3, 1),
|
||||||
|
('2026-02-03 11:20:00', 120.00, 'Card', 2, 1, 3),
|
||||||
|
('2026-02-05 14:50:00', 45.00, 'Cash', 4, 2, NULL),
|
||||||
|
('2026-02-08 16:15:00', 160.00, 'Debit', 1, 1, 2),
|
||||||
|
('2026-02-10 10:25:00', 100.00, 'Card', 5, 4, NULL),
|
||||||
|
('2026-02-12 13:45:00', 50.00, 'Cash', 2, 2, 1),
|
||||||
|
('2026-02-15 15:30:00', 85.00, 'Card', 3, 3, NULL),
|
||||||
|
('2026-02-18 11:10:00', 200.00, 'Card', 1, 1, 4),
|
||||||
|
('2026-02-20 14:35:00', 155.00, 'Debit', 4, 3, NULL),
|
||||||
|
('2026-02-22 16:50:00', 75.00, 'Cash', 2, 1, 2),
|
||||||
|
('2026-02-24 10:15:00', 140.00, 'Card', 5, 4, NULL),
|
||||||
|
(NOW(), 95.00, 'Card', 1, 1, 1);
|
||||||
|
|
||||||
|
INSERT INTO saleItem (saleId, prodId, quantity, unitPrice)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 2, 50.00),
|
||||||
|
(1, 6, 1, 25.00),
|
||||||
|
(2, 3, 1, 120.00),
|
||||||
|
(2, 4, 1, 80.00),
|
||||||
|
(3, 2, 3, 10.00),
|
||||||
|
(3, 5, 2, 15.00),
|
||||||
|
(4, 1, 3, 50.00),
|
||||||
|
(5, 4, 1, 80.00),
|
||||||
|
(6, 2, 4, 10.00),
|
||||||
|
(6, 5, 1, 15.00),
|
||||||
|
(6, 6, 1, 25.00),
|
||||||
|
(6, 1, 1, 50.00),
|
||||||
|
(7, 3, 2, 120.00),
|
||||||
|
(8, 1, 1, 50.00),
|
||||||
|
(8, 2, 3, 10.00),
|
||||||
|
(9, 1, 3, 50.00),
|
||||||
|
(9, 6, 1, 25.00),
|
||||||
|
(10, 3, 1, 120.00),
|
||||||
|
(11, 5, 1, 15.00),
|
||||||
|
(11, 2, 3, 10.00),
|
||||||
|
(12, 4, 2, 80.00),
|
||||||
|
(13, 6, 4, 25.00),
|
||||||
|
(14, 1, 1, 50.00),
|
||||||
|
(15, 2, 2, 10.00),
|
||||||
|
(15, 5, 1, 15.00),
|
||||||
|
(15, 6, 2, 25.00),
|
||||||
|
(16, 3, 1, 120.00),
|
||||||
|
(16, 4, 1, 80.00),
|
||||||
|
(17, 4, 1, 80.00),
|
||||||
|
(17, 1, 1, 50.00),
|
||||||
|
(17, 6, 1, 25.00),
|
||||||
|
(18, 6, 2, 25.00),
|
||||||
|
(18, 2, 2, 10.00),
|
||||||
|
(18, 5, 1, 15.00),
|
||||||
|
(19, 1, 2, 50.00),
|
||||||
|
(19, 6, 2, 25.00),
|
||||||
|
(20, 2, 5, 10.00),
|
||||||
|
(20, 5, 3, 15.00);
|
||||||
|
|
||||||
|
INSERT INTO purchaseOrder (supId, orderDate, status)
|
||||||
|
VALUES
|
||||||
|
(1, '2025-01-15', 'Delivered'),
|
||||||
|
(2, '2025-01-20', 'Pending'),
|
||||||
|
(3, '2025-02-01', 'Delivered'),
|
||||||
|
(4, '2025-02-10', 'In Transit'),
|
||||||
|
(1, '2025-02-15', 'Pending');
|
||||||
|
|
||||||
|
INSERT INTO activityLog (employeeId, activity)
|
||||||
|
VALUES
|
||||||
|
(1, 'Created new sale'),
|
||||||
|
(2, 'Booked appointment'),
|
||||||
|
(3, 'Completed grooming service'),
|
||||||
|
(4, 'Processed inventory order'),
|
||||||
|
(5, 'Conducted health checkup'),
|
||||||
|
(1, 'Updated customer information');
|
||||||
250
src/main/resources/schema.sql
Normal file
250
src/main/resources/schema.sql
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
-- Create Tables
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS storeLocation (
|
||||||
|
storeId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
storeName VARCHAR(100) NOT NULL,
|
||||||
|
address VARCHAR(255) NOT NULL,
|
||||||
|
phone VARCHAR(20) NOT NULL,
|
||||||
|
email VARCHAR(100) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS employee (
|
||||||
|
employeeId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
user_id BIGINT NULL,
|
||||||
|
firstName VARCHAR(50) NOT NULL,
|
||||||
|
lastName VARCHAR(50) NOT NULL,
|
||||||
|
email VARCHAR(100) NOT NULL,
|
||||||
|
phone VARCHAR(20) NOT NULL,
|
||||||
|
role VARCHAR(50) NOT NULL,
|
||||||
|
isActive BOOLEAN DEFAULT TRUE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT uk_employee_user_id UNIQUE (user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS employeeStore (
|
||||||
|
employeeId BIGINT NOT NULL,
|
||||||
|
storeId BIGINT NOT NULL,
|
||||||
|
PRIMARY KEY (employeeId, storeId),
|
||||||
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||||
|
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS customer (
|
||||||
|
customerId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
user_id BIGINT NULL,
|
||||||
|
firstName VARCHAR(50) NOT NULL,
|
||||||
|
lastName VARCHAR(50) NOT NULL,
|
||||||
|
email VARCHAR(100) NOT NULL,
|
||||||
|
phone VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT uk_customer_user_id UNIQUE (user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS pet (
|
||||||
|
petId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
petName VARCHAR(50) NOT NULL,
|
||||||
|
petSpecies VARCHAR(50) NOT NULL,
|
||||||
|
petBreed VARCHAR(50) NOT NULL,
|
||||||
|
petAge INT NOT NULL,
|
||||||
|
petStatus VARCHAR(20) NOT NULL,
|
||||||
|
petPrice DECIMAL(10, 2) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS adoption (
|
||||||
|
adoptionId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
petId BIGINT NOT NULL,
|
||||||
|
customerId BIGINT NOT NULL,
|
||||||
|
adoptionDate DATE NOT NULL,
|
||||||
|
adoptionStatus VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (petId) REFERENCES pet(petId),
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS supplier (
|
||||||
|
supId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
supCompany VARCHAR(100) NOT NULL,
|
||||||
|
supContactFirstName VARCHAR(50) NOT NULL,
|
||||||
|
supContactLastName VARCHAR(50) NOT NULL,
|
||||||
|
supEmail VARCHAR(100) NOT NULL,
|
||||||
|
supPhone VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS category (
|
||||||
|
categoryId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
categoryName VARCHAR(100) NOT NULL,
|
||||||
|
categoryType VARCHAR(50) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS product (
|
||||||
|
prodId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
prodName VARCHAR(100) NOT NULL,
|
||||||
|
prodPrice DECIMAL(10, 2) NOT NULL,
|
||||||
|
categoryId BIGINT NOT NULL,
|
||||||
|
prodDesc TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (categoryId) REFERENCES category(categoryId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS productSupplier (
|
||||||
|
supId BIGINT NOT NULL,
|
||||||
|
prodId BIGINT NOT NULL,
|
||||||
|
cost DECIMAL(10, 2) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (supId, prodId),
|
||||||
|
FOREIGN KEY (supId) REFERENCES supplier(supId),
|
||||||
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS inventory (
|
||||||
|
inventoryId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
prodId BIGINT NOT NULL,
|
||||||
|
quantity INT DEFAULT 0 NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS service (
|
||||||
|
serviceId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
serviceName VARCHAR(100) NOT NULL,
|
||||||
|
serviceDesc TEXT,
|
||||||
|
serviceDuration INT NOT NULL,
|
||||||
|
servicePrice DECIMAL(10, 2) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS appointment (
|
||||||
|
appointmentId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
serviceId BIGINT NOT NULL,
|
||||||
|
customerId BIGINT NOT NULL,
|
||||||
|
appointmentDate DATE NOT NULL,
|
||||||
|
appointmentTime TIME NOT NULL,
|
||||||
|
appointmentStatus VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (serviceId) REFERENCES service(serviceId),
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS appointmentPet (
|
||||||
|
appointmentId BIGINT NOT NULL,
|
||||||
|
petId BIGINT NOT NULL,
|
||||||
|
PRIMARY KEY (appointmentId, petId),
|
||||||
|
FOREIGN KEY (appointmentId) REFERENCES appointment(appointmentId),
|
||||||
|
FOREIGN KEY (petId) REFERENCES pet(petId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS sale (
|
||||||
|
saleId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
saleDate DATETIME NOT NULL,
|
||||||
|
totalAmount DECIMAL(10, 2) NOT NULL,
|
||||||
|
paymentMethod VARCHAR(50) NOT NULL,
|
||||||
|
employeeId BIGINT NOT NULL,
|
||||||
|
storeId BIGINT NOT NULL,
|
||||||
|
customerId BIGINT NULL,
|
||||||
|
isRefund BOOLEAN DEFAULT FALSE NOT NULL,
|
||||||
|
originalSaleId BIGINT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||||
|
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId),
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId),
|
||||||
|
FOREIGN KEY (originalSaleId) REFERENCES sale(saleId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS saleItem (
|
||||||
|
saleItemId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
saleId BIGINT NOT NULL,
|
||||||
|
prodId BIGINT NOT NULL,
|
||||||
|
quantity INT NOT NULL,
|
||||||
|
unitPrice DECIMAL(10, 2) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (saleId) REFERENCES sale(saleId),
|
||||||
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS purchaseOrder (
|
||||||
|
purchaseOrderId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
supId BIGINT NOT NULL,
|
||||||
|
orderDate DATE NOT NULL,
|
||||||
|
status VARCHAR(50) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (supId) REFERENCES supplier(supId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS activityLog (
|
||||||
|
logId BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
employeeId BIGINT NOT NULL,
|
||||||
|
activity TEXT NOT NULL,
|
||||||
|
logTimestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(100) UNIQUE,
|
||||||
|
fullName VARCHAR(100),
|
||||||
|
avatarUrl VARCHAR(255),
|
||||||
|
role VARCHAR(20) NOT NULL,
|
||||||
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS refund (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
saleId BIGINT NOT NULL,
|
||||||
|
customerId BIGINT NOT NULL,
|
||||||
|
amount DECIMAL(10, 2) NOT NULL,
|
||||||
|
reason VARCHAR(500) NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (saleId) REFERENCES sale(saleId),
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS conversation (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
customerId BIGINT NOT NULL,
|
||||||
|
staffId BIGINT,
|
||||||
|
status VARCHAR(20) DEFAULT 'OPEN',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId),
|
||||||
|
FOREIGN KEY (staffId) REFERENCES users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS message (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
conversationId BIGINT NOT NULL,
|
||||||
|
senderId BIGINT NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
isRead BOOLEAN DEFAULT FALSE,
|
||||||
|
FOREIGN KEY (conversationId) REFERENCES conversation(id),
|
||||||
|
FOREIGN KEY (senderId) REFERENCES users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Add foreign keys for user_id linkage
|
||||||
|
ALTER TABLE employee ADD CONSTRAINT fk_employee_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE customer ADD CONSTRAINT fk_customer_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.petshop.backend.util;
|
||||||
|
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
|
public class PasswordHashGenerator {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
System.out.println("admin123: " + encoder.encode("admin123"));
|
||||||
|
System.out.println("staff123: " + encoder.encode("staff123"));
|
||||||
|
System.out.println("customer123: " + encoder.encode("customer123"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user