Merge branch 'main' into AttachmentsToChat
This commit is contained in:
@@ -564,7 +564,7 @@
|
|||||||
"name": "Get All Pets",
|
"name": "Get All Pets",
|
||||||
"request": {
|
"request": {
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"url": "{{baseUrl}}/api/v1/pets",
|
"url": "{{baseUrl}}/api/v1/pets?status=available&storeId=1",
|
||||||
"header": [
|
"header": [
|
||||||
{
|
{
|
||||||
"key": "Content-Type",
|
"key": "Content-Type",
|
||||||
@@ -585,7 +585,10 @@
|
|||||||
"exec": [
|
"exec": [
|
||||||
"pm.test('Status code is 200', function () {",
|
"pm.test('Status code is 200', function () {",
|
||||||
" pm.response.to.have.status(200);",
|
" pm.response.to.have.status(200);",
|
||||||
"});"
|
"});",
|
||||||
|
"var json = pm.response.json();",
|
||||||
|
"pm.test('is page response', function () { pm.expect(json.content).to.be.an('array'); });",
|
||||||
|
"pm.test('all pets have storeName', function () { json.content.forEach(function(p) { pm.expect(p).to.have.property('storeName'); }); });"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -616,7 +619,10 @@
|
|||||||
"exec": [
|
"exec": [
|
||||||
"pm.test('Status code is 200', function () {",
|
"pm.test('Status code is 200', function () {",
|
||||||
" pm.response.to.have.status(200);",
|
" pm.response.to.have.status(200);",
|
||||||
"});"
|
"});",
|
||||||
|
"var json = pm.response.json();",
|
||||||
|
"pm.test('has petId', function () { pm.expect(json.petId).to.be.a('number'); });",
|
||||||
|
"pm.test('has owner fields', function () { pm.expect(json).to.have.all.keys('petId','petName','petSpecies','petBreed','petAge','petStatus','petPrice','imageUrl','createdAt','updatedAt','customerId','customerName','storeId','storeName'); });"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,7 +677,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"petName\": \"Postman Pet\",\n \"petSpecies\": \"Dog\",\n \"petBreed\": \"Mixed\",\n \"petAge\": 2,\n \"petStatus\": \"Available\",\n \"petPrice\": 350.00\n}",
|
"raw": "{\n \"petName\": \"Postman Pet\",\n \"petSpecies\": \"Dog\",\n \"petBreed\": \"Mixed\",\n \"petAge\": 2,\n \"petStatus\": \"Available\",\n \"petPrice\": 350.00,\n \"storeId\": 1\n}",
|
||||||
"options": {
|
"options": {
|
||||||
"raw": {
|
"raw": {
|
||||||
"language": "json"
|
"language": "json"
|
||||||
@@ -689,7 +695,11 @@
|
|||||||
" pm.response.to.have.status(201);",
|
" pm.response.to.have.status(201);",
|
||||||
"});",
|
"});",
|
||||||
"var jsonData = pm.response.json();",
|
"var jsonData = pm.response.json();",
|
||||||
"if (jsonData.petId !== undefined) pm.collectionVariables.set('petId', jsonData.petId);"
|
"if (jsonData.petId !== undefined) pm.collectionVariables.set('petId', jsonData.petId);",
|
||||||
|
"pm.test('has petId', function () { pm.expect(jsonData.petId).to.be.a('number'); });",
|
||||||
|
"pm.test('has storeId', function () { pm.expect(jsonData.storeId).to.equal(1); });",
|
||||||
|
"pm.test('has storeName', function () { pm.expect(jsonData.storeName).to.be.a('string'); });",
|
||||||
|
"pm.test('customerId is null', function () { pm.expect(jsonData.customerId).to.be.null; });"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,7 +723,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"petName\": \"Postman Pet Updated\",\n \"petSpecies\": \"Dog\",\n \"petBreed\": \"Mixed\",\n \"petAge\": 3,\n \"petStatus\": \"Available\",\n \"petPrice\": 375.00\n}",
|
"raw": "{\n \"petName\": \"Postman Pet Updated\",\n \"petSpecies\": \"Dog\",\n \"petBreed\": \"Mixed\",\n \"petAge\": 3,\n \"petStatus\": \"Owned\",\n \"petPrice\": 375.00,\n \"customerId\": 1\n}",
|
||||||
"options": {
|
"options": {
|
||||||
"raw": {
|
"raw": {
|
||||||
"language": "json"
|
"language": "json"
|
||||||
@@ -729,7 +739,12 @@
|
|||||||
"exec": [
|
"exec": [
|
||||||
"pm.test('Status code is 200', function () {",
|
"pm.test('Status code is 200', function () {",
|
||||||
" pm.response.to.have.status(200);",
|
" pm.response.to.have.status(200);",
|
||||||
"});"
|
"});",
|
||||||
|
"var json = pm.response.json();",
|
||||||
|
"pm.test('status is Owned', function () { pm.expect(json.petStatus).to.equal('Owned'); });",
|
||||||
|
"pm.test('has customerId', function () { pm.expect(json.customerId).to.be.a('number'); });",
|
||||||
|
"pm.test('has customerName', function () { pm.expect(json.customerName).to.be.a('string'); });",
|
||||||
|
"pm.test('storeId is null', function () { pm.expect(json.storeId).to.be.null; });"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ public class PetController {
|
|||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
@RequestParam(required = false) String species,
|
@RequestParam(required = false) String species,
|
||||||
@RequestParam(required = false) String status,
|
@RequestParam(required = false) String status,
|
||||||
|
@RequestParam(required = false) Long storeId,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(petService.getAllPets(q, species, status, pageable));
|
return ResponseEntity.ok(petService.getAllPets(q, species, status, storeId, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ public class PetRequest {
|
|||||||
|
|
||||||
private BigDecimal petPrice;
|
private BigDecimal petPrice;
|
||||||
|
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
private Long storeId;
|
||||||
|
|
||||||
public String getPetName() {
|
public String getPetName() {
|
||||||
return petName;
|
return petName;
|
||||||
}
|
}
|
||||||
@@ -71,6 +75,22 @@ public class PetRequest {
|
|||||||
this.petPrice = petPrice;
|
this.petPrice = petPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStoreId() {
|
||||||
|
return storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreId(Long storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -15,11 +15,15 @@ public class PetResponse {
|
|||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
private Long customerId;
|
||||||
|
private String customerName;
|
||||||
|
private Long storeId;
|
||||||
|
private String storeName;
|
||||||
|
|
||||||
public PetResponse() {
|
public PetResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PetResponse(Long petId, String petName, String petSpecies, String petBreed, Integer petAge, String petStatus, BigDecimal petPrice, String imageUrl, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
public PetResponse(Long petId, String petName, String petSpecies, String petBreed, Integer petAge, String petStatus, BigDecimal petPrice, String imageUrl, LocalDateTime createdAt, LocalDateTime updatedAt, Long customerId, String customerName, Long storeId, String storeName) {
|
||||||
this.petId = petId;
|
this.petId = petId;
|
||||||
this.petName = petName;
|
this.petName = petName;
|
||||||
this.petSpecies = petSpecies;
|
this.petSpecies = petSpecies;
|
||||||
@@ -30,6 +34,10 @@ public class PetResponse {
|
|||||||
this.imageUrl = imageUrl;
|
this.imageUrl = imageUrl;
|
||||||
this.createdAt = createdAt;
|
this.createdAt = createdAt;
|
||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.customerName = customerName;
|
||||||
|
this.storeId = storeId;
|
||||||
|
this.storeName = storeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getPetId() {
|
public Long getPetId() {
|
||||||
@@ -112,17 +120,49 @@ public class PetResponse {
|
|||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomerName() {
|
||||||
|
return customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerName(String customerName) {
|
||||||
|
this.customerName = customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStoreId() {
|
||||||
|
return storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreId(Long storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStoreName() {
|
||||||
|
return storeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreName(String storeName) {
|
||||||
|
this.storeName = storeName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
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;
|
||||||
PetResponse that = (PetResponse) o;
|
PetResponse that = (PetResponse) o;
|
||||||
return Objects.equals(petId, that.petId) && Objects.equals(petName, that.petName) && Objects.equals(petSpecies, that.petSpecies) && Objects.equals(petBreed, that.petBreed) && Objects.equals(petAge, that.petAge) && Objects.equals(petStatus, that.petStatus) && Objects.equals(petPrice, that.petPrice) && Objects.equals(imageUrl, that.imageUrl) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
|
return Objects.equals(petId, that.petId) && Objects.equals(petName, that.petName) && Objects.equals(petSpecies, that.petSpecies) && Objects.equals(petBreed, that.petBreed) && Objects.equals(petAge, that.petAge) && Objects.equals(petStatus, that.petStatus) && Objects.equals(petPrice, that.petPrice) && Objects.equals(imageUrl, that.imageUrl) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt) && Objects.equals(customerId, that.customerId) && Objects.equals(customerName, that.customerName) && Objects.equals(storeId, that.storeId) && Objects.equals(storeName, that.storeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(petId, petName, petSpecies, petBreed, petAge, petStatus, petPrice, imageUrl, createdAt, updatedAt);
|
return Objects.hash(petId, petName, petSpecies, petBreed, petAge, petStatus, petPrice, imageUrl, createdAt, updatedAt, customerId, customerName, storeId, storeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -138,6 +178,10 @@ public class PetResponse {
|
|||||||
", imageUrl='" + imageUrl + '\'' +
|
", imageUrl='" + imageUrl + '\'' +
|
||||||
", createdAt=" + createdAt +
|
", createdAt=" + createdAt +
|
||||||
", updatedAt=" + updatedAt +
|
", updatedAt=" + updatedAt +
|
||||||
|
", customerId=" + customerId +
|
||||||
|
", customerName='" + customerName + '\'' +
|
||||||
|
", storeId=" + storeId +
|
||||||
|
", storeName='" + storeName + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ public class Pet {
|
|||||||
@Column(length = 255)
|
@Column(length = 255)
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "customerId")
|
||||||
|
private Customer customer;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "storeId")
|
||||||
|
private StoreLocation store;
|
||||||
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(name = "created_at", updatable = false)
|
@Column(name = "created_at", updatable = false)
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
@@ -142,6 +150,22 @@ public class Pet {
|
|||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Customer getCustomer() {
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomer(Customer customer) {
|
||||||
|
this.customer = customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StoreLocation getStore() {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStore(StoreLocation store) {
|
||||||
|
this.store = store;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -18,16 +18,18 @@ public interface PetRepository extends JpaRepository<Pet, Long> {
|
|||||||
@Query("SELECT p FROM Pet p WHERE " +
|
@Query("SELECT p FROM Pet p WHERE " +
|
||||||
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
||||||
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
|
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
|
||||||
"(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status))")
|
"(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status)) AND " +
|
||||||
Page<Pet> searchPets(@Param("q") String query, @Param("species") String species, @Param("status") String status, Pageable pageable);
|
"(:storeId IS NULL OR p.store.storeId = :storeId)")
|
||||||
|
Page<Pet> searchPets(@Param("q") String query, @Param("species") String species, @Param("status") String status, @Param("storeId") Long storeId, Pageable pageable);
|
||||||
|
|
||||||
@Query("SELECT p FROM Pet p WHERE LOWER(p.petStatus) = 'available' AND " +
|
@Query("SELECT p FROM Pet p WHERE LOWER(p.petStatus) = 'available' AND " +
|
||||||
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
||||||
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species))")
|
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
|
||||||
Page<Pet> searchPublicPets(@Param("q") String query, @Param("species") String species, Pageable pageable);
|
"(:storeId IS NULL OR p.store.storeId = :storeId)")
|
||||||
|
Page<Pet> searchPublicPets(@Param("q") String query, @Param("species") String species, @Param("storeId") Long storeId, Pageable pageable);
|
||||||
|
|
||||||
@Query("SELECT DISTINCT p FROM Pet p LEFT JOIN Adoption a ON a.pet = p AND LOWER(a.adoptionStatus) = 'completed' WHERE " +
|
@Query("SELECT DISTINCT p FROM Pet p LEFT JOIN Adoption a ON a.pet = p AND LOWER(a.adoptionStatus) = 'completed' WHERE " +
|
||||||
"(LOWER(p.petStatus) = 'available' OR a.customer.userId = :userId) AND " +
|
"(LOWER(p.petStatus) = 'available' OR a.customer.userId = :userId OR (LOWER(p.petStatus) = 'owned' AND p.customer.userId = :userId)) AND " +
|
||||||
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
"(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petBreed) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
||||||
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
|
"(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
|
||||||
"(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status))")
|
"(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status))")
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import com.petshop.backend.dto.common.BulkDeleteRequest;
|
|||||||
import com.petshop.backend.dto.pet.PetRequest;
|
import com.petshop.backend.dto.pet.PetRequest;
|
||||||
import com.petshop.backend.dto.pet.PetResponse;
|
import com.petshop.backend.dto.pet.PetResponse;
|
||||||
import com.petshop.backend.entity.Adoption;
|
import com.petshop.backend.entity.Adoption;
|
||||||
|
import com.petshop.backend.entity.Customer;
|
||||||
import com.petshop.backend.entity.Pet;
|
import com.petshop.backend.entity.Pet;
|
||||||
|
import com.petshop.backend.entity.StoreLocation;
|
||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
import com.petshop.backend.security.AppPrincipal;
|
import com.petshop.backend.security.AppPrincipal;
|
||||||
import com.petshop.backend.repository.AdoptionRepository;
|
import com.petshop.backend.repository.AdoptionRepository;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
import com.petshop.backend.repository.PetRepository;
|
import com.petshop.backend.repository.PetRepository;
|
||||||
|
import com.petshop.backend.repository.StoreRepository;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -29,15 +33,20 @@ public class PetService {
|
|||||||
|
|
||||||
private final PetRepository petRepository;
|
private final PetRepository petRepository;
|
||||||
private final AdoptionRepository adoptionRepository;
|
private final AdoptionRepository adoptionRepository;
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
private final StoreRepository storeRepository;
|
||||||
private final CatalogImageStorageService catalogImageStorageService;
|
private final CatalogImageStorageService catalogImageStorageService;
|
||||||
|
|
||||||
public PetService(PetRepository petRepository, AdoptionRepository adoptionRepository, CatalogImageStorageService catalogImageStorageService) {
|
public PetService(PetRepository petRepository, AdoptionRepository adoptionRepository, CustomerRepository customerRepository, StoreRepository storeRepository, CatalogImageStorageService catalogImageStorageService) {
|
||||||
this.petRepository = petRepository;
|
this.petRepository = petRepository;
|
||||||
this.adoptionRepository = adoptionRepository;
|
this.adoptionRepository = adoptionRepository;
|
||||||
|
this.customerRepository = customerRepository;
|
||||||
|
this.storeRepository = storeRepository;
|
||||||
this.catalogImageStorageService = catalogImageStorageService;
|
this.catalogImageStorageService = catalogImageStorageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<PetResponse> getAllPets(String query, String species, String status, Pageable pageable) {
|
@Transactional(readOnly = true)
|
||||||
|
public Page<PetResponse> getAllPets(String query, String species, String status, Long storeId, Pageable pageable) {
|
||||||
String normalizedQuery = normalizeFilter(query);
|
String normalizedQuery = normalizeFilter(query);
|
||||||
String normalizedSpecies = normalizeFilter(species);
|
String normalizedSpecies = normalizeFilter(species);
|
||||||
String normalizedStatus = normalizeFilter(status);
|
String normalizedStatus = normalizeFilter(status);
|
||||||
@@ -48,22 +57,23 @@ public class PetService {
|
|||||||
if (!isAllowedPublicStatus(normalizedStatus)) {
|
if (!isAllowedPublicStatus(normalizedStatus)) {
|
||||||
return new PageImpl<>(java.util.List.of(), pageable, 0);
|
return new PageImpl<>(java.util.List.of(), pageable, 0);
|
||||||
}
|
}
|
||||||
pets = petRepository.searchPublicPets(normalizedQuery, normalizedSpecies, pageable);
|
pets = petRepository.searchPublicPets(normalizedQuery, normalizedSpecies, storeId, pageable);
|
||||||
} else if (viewer.role() == User.Role.STAFF || viewer.role() == User.Role.ADMIN) {
|
} else if (viewer.role() == User.Role.STAFF || viewer.role() == User.Role.ADMIN) {
|
||||||
pets = petRepository.searchPets(normalizedQuery, normalizedSpecies, normalizedStatus, pageable);
|
pets = petRepository.searchPets(normalizedQuery, normalizedSpecies, normalizedStatus, storeId, pageable);
|
||||||
} else if (viewer.role() == User.Role.CUSTOMER) {
|
} else if (viewer.role() == User.Role.CUSTOMER) {
|
||||||
if (!isAllowedCustomerStatus(normalizedStatus)) {
|
if (!isAllowedCustomerStatus(normalizedStatus)) {
|
||||||
return new PageImpl<>(java.util.List.of(), pageable, 0);
|
return new PageImpl<>(java.util.List.of(), pageable, 0);
|
||||||
}
|
}
|
||||||
pets = petRepository.searchCustomerVisiblePets(viewer.userId(), normalizedQuery, normalizedSpecies, normalizedStatus, pageable);
|
pets = petRepository.searchCustomerVisiblePets(viewer.userId(), normalizedQuery, normalizedSpecies, normalizedStatus, pageable);
|
||||||
} else {
|
} else {
|
||||||
pets = petRepository.searchPublicPets(normalizedQuery, normalizedSpecies, pageable);
|
pets = petRepository.searchPublicPets(normalizedQuery, normalizedSpecies, storeId, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pets
|
return pets
|
||||||
.map(this::mapToResponse);
|
.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
public PetResponse getPetById(Long id) {
|
public PetResponse getPetById(Long id) {
|
||||||
Pet pet = petRepository.findById(id)
|
Pet pet = petRepository.findById(id)
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Pet not found with id: " + id));
|
.orElseThrow(() -> new ResourceNotFoundException("Pet not found with id: " + id));
|
||||||
@@ -82,6 +92,7 @@ public class PetService {
|
|||||||
pet.setPetAge(request.getPetAge());
|
pet.setPetAge(request.getPetAge());
|
||||||
pet.setPetStatus(request.getPetStatus());
|
pet.setPetStatus(request.getPetStatus());
|
||||||
pet.setPetPrice(request.getPetPrice());
|
pet.setPetPrice(request.getPetPrice());
|
||||||
|
applyOwnerAndStore(pet, request);
|
||||||
|
|
||||||
pet = petRepository.save(pet);
|
pet = petRepository.save(pet);
|
||||||
return mapToResponse(pet);
|
return mapToResponse(pet);
|
||||||
@@ -98,6 +109,7 @@ public class PetService {
|
|||||||
pet.setPetAge(request.getPetAge());
|
pet.setPetAge(request.getPetAge());
|
||||||
pet.setPetStatus(request.getPetStatus());
|
pet.setPetStatus(request.getPetStatus());
|
||||||
pet.setPetPrice(request.getPetPrice());
|
pet.setPetPrice(request.getPetPrice());
|
||||||
|
applyOwnerAndStore(pet, request);
|
||||||
|
|
||||||
pet = petRepository.save(pet);
|
pet = petRepository.save(pet);
|
||||||
return mapToResponse(pet);
|
return mapToResponse(pet);
|
||||||
@@ -161,6 +173,9 @@ public class PetService {
|
|||||||
if (viewer == null || viewer.userId() == null) {
|
if (viewer == null || viewer.userId() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (isOwnedByUser(pet, viewer.userId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return isAdoptedByUser(pet, viewer.userId());
|
return isAdoptedByUser(pet, viewer.userId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +245,7 @@ public class PetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAllowedCustomerStatus(String status) {
|
private boolean isAllowedCustomerStatus(String status) {
|
||||||
return status == null || "available".equalsIgnoreCase(status) || "adopted".equalsIgnoreCase(status);
|
return status == null || "available".equalsIgnoreCase(status) || "adopted".equalsIgnoreCase(status) || "owned".equalsIgnoreCase(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String normalizeFilter(String value) {
|
private String normalizeFilter(String value) {
|
||||||
@@ -242,6 +257,8 @@ public class PetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PetResponse mapToResponse(Pet pet) {
|
private PetResponse mapToResponse(Pet pet) {
|
||||||
|
Customer customer = pet.getCustomer();
|
||||||
|
StoreLocation store = pet.getStore();
|
||||||
return new PetResponse(
|
return new PetResponse(
|
||||||
pet.getPetId(),
|
pet.getPetId(),
|
||||||
pet.getPetName(),
|
pet.getPetName(),
|
||||||
@@ -252,10 +269,59 @@ public class PetService {
|
|||||||
pet.getPetPrice(),
|
pet.getPetPrice(),
|
||||||
pet.getImageUrl() != null && !pet.getImageUrl().isBlank() ? "/api/v1/pets/" + pet.getPetId() + "/image" : null,
|
pet.getImageUrl() != null && !pet.getImageUrl().isBlank() ? "/api/v1/pets/" + pet.getPetId() + "/image" : null,
|
||||||
pet.getCreatedAt(),
|
pet.getCreatedAt(),
|
||||||
pet.getUpdatedAt()
|
pet.getUpdatedAt(),
|
||||||
|
customer != null ? customer.getCustomerId() : null,
|
||||||
|
customer != null ? customer.getFirstName() + " " + customer.getLastName() : null,
|
||||||
|
store != null ? store.getStoreId() : null,
|
||||||
|
store != null ? store.getStoreName() : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyOwnerAndStore(Pet pet, PetRequest request) {
|
||||||
|
if ("owned".equalsIgnoreCase(request.getPetStatus())) {
|
||||||
|
if (request.getCustomerId() != null) {
|
||||||
|
Customer customer = customerRepository.findById(request.getCustomerId())
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer not found with id: " + request.getCustomerId()));
|
||||||
|
pet.setCustomer(customer);
|
||||||
|
} else {
|
||||||
|
pet.setCustomer(null);
|
||||||
|
}
|
||||||
|
pet.setStore(null);
|
||||||
|
} else if ("available".equalsIgnoreCase(request.getPetStatus()) || "unadopted".equalsIgnoreCase(request.getPetStatus())) {
|
||||||
|
if (request.getStoreId() != null) {
|
||||||
|
StoreLocation store = storeRepository.findById(request.getStoreId())
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()));
|
||||||
|
pet.setStore(store);
|
||||||
|
} else {
|
||||||
|
pet.setStore(null);
|
||||||
|
}
|
||||||
|
pet.setCustomer(null);
|
||||||
|
} else {
|
||||||
|
if (request.getCustomerId() != null) {
|
||||||
|
Customer customer = customerRepository.findById(request.getCustomerId())
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Customer not found with id: " + request.getCustomerId()));
|
||||||
|
pet.setCustomer(customer);
|
||||||
|
} else {
|
||||||
|
pet.setCustomer(null);
|
||||||
|
}
|
||||||
|
if (request.getStoreId() != null) {
|
||||||
|
StoreLocation store = storeRepository.findById(request.getStoreId())
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()));
|
||||||
|
pet.setStore(store);
|
||||||
|
} else {
|
||||||
|
pet.setStore(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOwnedByUser(Pet pet, Long userId) {
|
||||||
|
if (!"owned".equalsIgnoreCase(normalizeStatus(pet.getPetStatus()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Customer customer = pet.getCustomer();
|
||||||
|
return customer != null && userId.equals(customer.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
public record ImagePayload(Resource resource, MediaType mediaType) {
|
public record ImagePayload(Resource resource, MediaType mediaType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
ALTER TABLE pet ADD COLUMN customerId BIGINT NULL;
|
||||||
|
ALTER TABLE pet ADD COLUMN storeId BIGINT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE pet ADD CONSTRAINT fk_pet_customer
|
||||||
|
FOREIGN KEY (customerId) REFERENCES customer(customerId);
|
||||||
|
ALTER TABLE pet ADD CONSTRAINT fk_pet_store
|
||||||
|
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId);
|
||||||
|
|
||||||
|
CREATE INDEX idx_pet_customerId ON pet(customerId);
|
||||||
|
CREATE INDEX idx_pet_storeId ON pet(storeId);
|
||||||
|
|
||||||
|
UPDATE pet
|
||||||
|
SET storeId = (SELECT storeId FROM storeLocation ORDER BY storeId ASC LIMIT 1)
|
||||||
|
WHERE LOWER(petStatus) IN ('available', 'unadopted');
|
||||||
|
|
||||||
|
UPDATE pet p
|
||||||
|
JOIN (
|
||||||
|
SELECT a.petId, a.customerId
|
||||||
|
FROM adoption a
|
||||||
|
WHERE LOWER(a.adoptionStatus) = 'completed'
|
||||||
|
) latest ON latest.petId = p.petId
|
||||||
|
SET p.customerId = latest.customerId
|
||||||
|
WHERE LOWER(p.petStatus) = 'adopted';
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice, customerId)
|
||||||
|
VALUES
|
||||||
|
('Pepper', 'Cat', 'Tabby', 3, 'Owned', 0.00, 1),
|
||||||
|
('Coco', 'Dog', 'Pomeranian', 2, 'Owned', 0.00, 4),
|
||||||
|
('Finn', 'Dog', 'Border Collie', 5, 'Owned', 0.00, 6);
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
INSERT INTO customer (firstName, lastName, email) VALUES
|
||||||
|
('Noah', 'Parker', 'noah@gmail.com'),
|
||||||
|
('Mia', 'Evans', 'mia@gmail.com'),
|
||||||
|
('Ethan', 'Scott', 'ethan@gmail.com'),
|
||||||
|
('Chloe', 'Adams', 'chloe@gmail.com'),
|
||||||
|
('Lucas', 'Baker', 'lucas@gmail.com'),
|
||||||
|
('Lily', 'Hall', 'lily@gmail.com'),
|
||||||
|
('Mason', 'Rivera', 'mason@gmail.com'),
|
||||||
|
('Ella', 'Mitchell', 'ella@gmail.com'),
|
||||||
|
('James', 'Carter', 'jcarter@gmail.com'),
|
||||||
|
('Harper', 'Collins', 'harper@gmail.com');
|
||||||
|
|
||||||
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice, storeId) VALUES
|
||||||
|
('Rocky', 'Dog', 'German Shepherd', 1, 'Available', 475.00, 1),
|
||||||
|
('Daisy', 'Dog', 'Poodle', 2, 'Available', 512.00, 1),
|
||||||
|
('Cooper', 'Dog', 'Bulldog', 3, 'Available', 560.00, 1),
|
||||||
|
('Ruby', 'Dog', 'Boxer', 4, 'Available', 575.00, 1),
|
||||||
|
('Tucker', 'Dog', 'Dachshund', 5, 'Available', 634.00, 1),
|
||||||
|
('Rosie', 'Dog', 'Shih Tzu', 1, 'Available', 660.00, 2),
|
||||||
|
('Bear', 'Dog', 'Rottweiler', 2, 'Available', 686.00, 2),
|
||||||
|
('Maggie', 'Dog', 'Corgi', 3, 'Available', 745.00, 2),
|
||||||
|
('Leo', 'Dog', 'Husky', 4, 'Available', 749.00, 2),
|
||||||
|
('Zoey', 'Cat', 'Ragdoll', 1, 'Available', 420.00, 1),
|
||||||
|
('Oliver', 'Cat', 'British Shorthair', 2, 'Available', 395.00, 1),
|
||||||
|
('Lola', 'Cat', 'Bengal', 3, 'Available', 465.00, 3),
|
||||||
|
('Buster', 'Dog', 'Beagle', 2, 'Available', 440.00, 3),
|
||||||
|
('Sadie', 'Dog', 'Golden Retriever', 1, 'Available', 535.00, 3),
|
||||||
|
('Toby', 'Dog', 'Labrador', 5, 'Available', 490.00, 1),
|
||||||
|
('Cleo', 'Cat', 'Abyssinian', 2, 'Available', 375.00, 2),
|
||||||
|
('Harley', 'Dog', 'Dalmatian', 3, 'Available', 520.00, 1),
|
||||||
|
('Mocha', 'Cat', 'Burmese', 1, 'Available', 345.00, 3),
|
||||||
|
('Rex', 'Dog', 'Doberman', 4, 'Available', 610.00, 1),
|
||||||
|
('Willow', 'Cat', 'Scottish Fold', 2, 'Available', 480.00, 2),
|
||||||
|
('Gizmo', 'Dog', 'Pomeranian', 1, 'Available', 530.00, 1),
|
||||||
|
('Nala', 'Cat', 'Siamese', 3, 'Available', 360.00, 2),
|
||||||
|
('Duke', 'Dog', 'Great Dane', 2, 'Available', 720.00, 3),
|
||||||
|
('Misty', 'Cat', 'Russian Blue', 4, 'Available', 410.00, 1),
|
||||||
|
('Ace', 'Dog', 'Australian Shepherd', 1, 'Available', 555.00, 1);
|
||||||
|
|
||||||
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice, customerId) VALUES
|
||||||
|
('Shadow', 'Dog', 'Labrador', 3, 'Adopted', 500.00, 1),
|
||||||
|
('Kitty', 'Cat', 'Persian', 2, 'Adopted', 320.00, 2),
|
||||||
|
('Bruno', 'Dog', 'Rottweiler', 4, 'Adopted', 580.00, 3),
|
||||||
|
('Snowball', 'Cat', 'Turkish Angora', 1, 'Adopted', 390.00, 4),
|
||||||
|
('Zeus', 'Dog', 'Husky', 3, 'Adopted', 640.00, 5);
|
||||||
|
|
||||||
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice, customerId) VALUES
|
||||||
|
('Biscuit', 'Dog', 'Beagle', 2, 'Owned', 0.00, 6),
|
||||||
|
('Patches', 'Cat', 'Calico', 5, 'Owned', 0.00, 7),
|
||||||
|
('Scout', 'Dog', 'Border Collie', 3, 'Owned', 0.00, 8),
|
||||||
|
('Mittens', 'Cat', 'Domestic Short', 4, 'Owned', 0.00, 9),
|
||||||
|
('Thor', 'Dog', 'German Shepherd', 2, 'Owned', 0.00, 10);
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, employeeId, adoptionDate, adoptionStatus)
|
||||||
|
SELECT p.petId, p.customerId,
|
||||||
|
(SELECT e.employeeId FROM employee e JOIN users u ON u.id = e.user_id
|
||||||
|
WHERE e.isActive = TRUE AND u.role = 'STAFF' ORDER BY e.employeeId LIMIT 1),
|
||||||
|
'2026-01-10', 'Completed'
|
||||||
|
FROM pet p WHERE p.petName = 'Shadow' AND p.petStatus = 'Adopted';
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, employeeId, adoptionDate, adoptionStatus)
|
||||||
|
SELECT p.petId, p.customerId,
|
||||||
|
(SELECT e.employeeId FROM employee e JOIN users u ON u.id = e.user_id
|
||||||
|
WHERE e.isActive = TRUE AND u.role = 'STAFF' ORDER BY e.employeeId LIMIT 1),
|
||||||
|
'2026-01-18', 'Completed'
|
||||||
|
FROM pet p WHERE p.petName = 'Kitty' AND p.petStatus = 'Adopted';
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, employeeId, adoptionDate, adoptionStatus)
|
||||||
|
SELECT p.petId, p.customerId,
|
||||||
|
(SELECT e.employeeId FROM employee e JOIN users u ON u.id = e.user_id
|
||||||
|
WHERE e.isActive = TRUE AND u.role = 'STAFF' ORDER BY e.employeeId LIMIT 1),
|
||||||
|
'2026-02-03', 'Completed'
|
||||||
|
FROM pet p WHERE p.petName = 'Bruno' AND p.petStatus = 'Adopted';
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, employeeId, adoptionDate, adoptionStatus)
|
||||||
|
SELECT p.petId, p.customerId,
|
||||||
|
(SELECT e.employeeId FROM employee e JOIN users u ON u.id = e.user_id
|
||||||
|
WHERE e.isActive = TRUE AND u.role = 'STAFF' ORDER BY e.employeeId LIMIT 1),
|
||||||
|
'2026-02-14', 'Completed'
|
||||||
|
FROM pet p WHERE p.petName = 'Snowball' AND p.petStatus = 'Adopted';
|
||||||
|
|
||||||
|
INSERT INTO adoption (petId, customerId, employeeId, adoptionDate, adoptionStatus)
|
||||||
|
SELECT p.petId, p.customerId,
|
||||||
|
(SELECT e.employeeId FROM employee e JOIN users u ON u.id = e.user_id
|
||||||
|
WHERE e.isActive = TRUE AND u.role = 'STAFF' ORDER BY e.employeeId LIMIT 1),
|
||||||
|
'2026-02-21', 'Completed'
|
||||||
|
FROM pet p WHERE p.petName = 'Zeus' AND p.petStatus = 'Adopted';
|
||||||
|
|
||||||
|
INSERT INTO customer_pet (customer_id, pet_name, species, breed) VALUES
|
||||||
|
(1, 'Rex', 'Dog', 'German Shepherd'),
|
||||||
|
(2, 'Whiskers', 'Cat', 'Tabby'),
|
||||||
|
(3, 'Goldie', 'Dog', 'Golden Retriever'),
|
||||||
|
(4, 'Midnight', 'Cat', 'Black'),
|
||||||
|
(5, 'Storm', 'Dog', 'Husky'),
|
||||||
|
(6, 'Peanut', 'Dog', 'Poodle'),
|
||||||
|
(7, 'Snowball', 'Cat', 'Persian'),
|
||||||
|
(8, 'Duke', 'Dog', 'Labrador'),
|
||||||
|
(9, 'Luna', 'Cat', 'Siamese'),
|
||||||
|
(10, 'Buster', 'Dog', 'Beagle'),
|
||||||
|
(11, 'Daisy', 'Dog', 'Corgi'),
|
||||||
|
(12, 'Cleo', 'Cat', 'Ragdoll');
|
||||||
|
|
||||||
|
INSERT INTO appointment (serviceId, customerId, appointmentDate, appointmentTime, appointmentStatus, storeId, employeeId) VALUES
|
||||||
|
(1, 1, '2026-01-10', '09:00:00', 'Completed', 1, 1),
|
||||||
|
(2, 2, '2026-01-10', '11:00:00', 'Completed', 1, 1),
|
||||||
|
(3, 3, '2026-01-17', '09:00:00', 'Missed', 1, 1),
|
||||||
|
(4, 4, '2026-01-17', '14:00:00', 'Completed', 1, 1),
|
||||||
|
(5, 5, '2026-01-24', '10:00:00', 'Completed', 1, 1),
|
||||||
|
(1, 6, '2026-01-24', '13:00:00', 'Missed', 1, 1),
|
||||||
|
(2, 7, '2026-02-07', '09:00:00', 'Completed', 1, 1),
|
||||||
|
(3, 8, '2026-02-07', '11:00:00', 'Completed', 1, 1),
|
||||||
|
(1, 9, '2026-01-11', '09:00:00', 'Completed', 1, 2),
|
||||||
|
(2, 10, '2026-01-11', '11:00:00', 'Missed', 1, 2),
|
||||||
|
(3, 11, '2026-01-18', '10:00:00', 'Completed', 1, 2),
|
||||||
|
(4, 12, '2026-01-18', '13:00:00', 'Completed', 1, 2),
|
||||||
|
(5, 1, '2026-02-01', '09:00:00', 'Completed', 1, 2),
|
||||||
|
(1, 2, '2026-02-01', '14:00:00', 'Missed', 1, 2),
|
||||||
|
(2, 3, '2026-02-08', '10:00:00', 'Completed', 1, 2),
|
||||||
|
(3, 4, '2026-02-08', '13:00:00', 'Completed', 1, 2),
|
||||||
|
(4, 5, '2026-01-12', '09:00:00', 'Completed', 1, 5),
|
||||||
|
(5, 6, '2026-01-12', '11:00:00', 'Completed', 1, 5),
|
||||||
|
(1, 7, '2026-01-19', '09:00:00', 'Missed', 1, 5),
|
||||||
|
(2, 8, '2026-01-19', '14:00:00', 'Completed', 1, 5),
|
||||||
|
(3, 9, '2026-02-09', '10:00:00', 'Completed', 1, 5),
|
||||||
|
(4, 10, '2026-02-09', '13:00:00', 'Completed', 1, 5),
|
||||||
|
(1, 11, '2026-01-13', '09:00:00', 'Completed', 2, 3),
|
||||||
|
(2, 12, '2026-01-13', '11:00:00', 'Completed', 2, 3),
|
||||||
|
(3, 1, '2026-02-10', '09:00:00', 'Missed', 2, 3),
|
||||||
|
(4, 2, '2026-02-10', '13:00:00', 'Completed', 2, 3),
|
||||||
|
(1, 3, '2026-01-14', '10:00:00', 'Completed', 3, 4),
|
||||||
|
(2, 4, '2026-01-14', '13:00:00', 'Completed', 3, 4),
|
||||||
|
(3, 5, '2026-02-11', '10:00:00', 'Missed', 3, 4),
|
||||||
|
(4, 6, '2026-02-11', '14:00:00', 'Completed', 3, 4),
|
||||||
|
(1, 7, '2026-04-15', '09:00:00', 'Booked', 1, 1),
|
||||||
|
(2, 8, '2026-04-15', '11:00:00', 'Booked', 1, 2),
|
||||||
|
(3, 9, '2026-04-16', '10:00:00', 'Booked', 1, 5),
|
||||||
|
(4, 10, '2026-04-17', '09:00:00', 'Booked', 2, 3),
|
||||||
|
(5, 11, '2026-04-18', '14:00:00', 'Booked', 3, 4);
|
||||||
|
|
||||||
|
INSERT INTO appointment_customer_pet (appointment_id, customer_pet_id)
|
||||||
|
SELECT a.appointmentId,
|
||||||
|
(((a.appointmentId - 6) % 12) + 1)
|
||||||
|
FROM appointment a
|
||||||
|
WHERE a.appointmentId BETWEEN 6 AND 40;
|
||||||
@@ -6,7 +6,9 @@ import com.petshop.backend.entity.Pet;
|
|||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
import com.petshop.backend.repository.AdoptionRepository;
|
import com.petshop.backend.repository.AdoptionRepository;
|
||||||
|
import com.petshop.backend.repository.CustomerRepository;
|
||||||
import com.petshop.backend.repository.PetRepository;
|
import com.petshop.backend.repository.PetRepository;
|
||||||
|
import com.petshop.backend.repository.StoreRepository;
|
||||||
import com.petshop.backend.security.AppPrincipal;
|
import com.petshop.backend.security.AppPrincipal;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -39,6 +41,12 @@ class PetServiceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private AdoptionRepository adoptionRepository;
|
private AdoptionRepository adoptionRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private StoreRepository storeRepository;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CatalogImageStorageService catalogImageStorageService;
|
private CatalogImageStorageService catalogImageStorageService;
|
||||||
|
|
||||||
@@ -54,24 +62,24 @@ class PetServiceTest {
|
|||||||
void getAllPetsAnonymousReturnsOnlyPublicPets() {
|
void getAllPetsAnonymousReturnsOnlyPublicPets() {
|
||||||
Pageable pageable = PageRequest.of(0, 10);
|
Pageable pageable = PageRequest.of(0, 10);
|
||||||
Pet availablePet = pet(1L, "Buddy", "Available");
|
Pet availablePet = pet(1L, "Buddy", "Available");
|
||||||
when(petRepository.searchPublicPets(null, null, pageable)).thenReturn(new PageImpl<>(List.of(availablePet), pageable, 1));
|
when(petRepository.searchPublicPets(null, null, null, pageable)).thenReturn(new PageImpl<>(List.of(availablePet), pageable, 1));
|
||||||
|
|
||||||
var result = petService.getAllPets(null, null, null, pageable);
|
var result = petService.getAllPets(null, null, null, null, pageable);
|
||||||
|
|
||||||
assertEquals(1, result.getTotalElements());
|
assertEquals(1, result.getTotalElements());
|
||||||
assertEquals("Buddy", result.getContent().get(0).getPetName());
|
assertEquals("Buddy", result.getContent().get(0).getPetName());
|
||||||
verify(petRepository).searchPublicPets(null, null, pageable);
|
verify(petRepository).searchPublicPets(null, null, null, pageable);
|
||||||
verify(petRepository, never()).searchPets(null, null, null, pageable);
|
verify(petRepository, never()).searchPets(null, null, null, null, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getAllPetsAnonymousWithAdoptedStatusReturnsEmptyPage() {
|
void getAllPetsAnonymousWithAdoptedStatusReturnsEmptyPage() {
|
||||||
Pageable pageable = PageRequest.of(0, 10);
|
Pageable pageable = PageRequest.of(0, 10);
|
||||||
|
|
||||||
var result = petService.getAllPets(null, null, "Adopted", pageable);
|
var result = petService.getAllPets(null, null, "Adopted", null, pageable);
|
||||||
|
|
||||||
assertEquals(0, result.getTotalElements());
|
assertEquals(0, result.getTotalElements());
|
||||||
verify(petRepository, never()).searchPublicPets(null, null, pageable);
|
verify(petRepository, never()).searchPublicPets(null, null, null, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -83,7 +91,7 @@ class PetServiceTest {
|
|||||||
when(petRepository.searchCustomerVisiblePets(25L, null, null, null, pageable))
|
when(petRepository.searchCustomerVisiblePets(25L, null, null, null, pageable))
|
||||||
.thenReturn(new PageImpl<>(List.of(availablePet, adoptedPet), pageable, 2));
|
.thenReturn(new PageImpl<>(List.of(availablePet, adoptedPet), pageable, 2));
|
||||||
|
|
||||||
var result = petService.getAllPets(null, null, null, pageable);
|
var result = petService.getAllPets(null, null, null, null, pageable);
|
||||||
|
|
||||||
assertEquals(2, result.getTotalElements());
|
assertEquals(2, result.getTotalElements());
|
||||||
verify(petRepository).searchCustomerVisiblePets(25L, null, null, null, pageable);
|
verify(petRepository).searchCustomerVisiblePets(25L, null, null, null, pageable);
|
||||||
@@ -95,13 +103,13 @@ class PetServiceTest {
|
|||||||
setAuthentication(99L, User.Role.ADMIN);
|
setAuthentication(99L, User.Role.ADMIN);
|
||||||
Pet availablePet = pet(1L, "Buddy", "Available");
|
Pet availablePet = pet(1L, "Buddy", "Available");
|
||||||
Pet adoptedPet = pet(2L, "Luna", "Adopted");
|
Pet adoptedPet = pet(2L, "Luna", "Adopted");
|
||||||
when(petRepository.searchPets(null, null, null, pageable))
|
when(petRepository.searchPets(null, null, null, null, pageable))
|
||||||
.thenReturn(new PageImpl<>(List.of(availablePet, adoptedPet), pageable, 2));
|
.thenReturn(new PageImpl<>(List.of(availablePet, adoptedPet), pageable, 2));
|
||||||
|
|
||||||
var result = petService.getAllPets(null, null, null, pageable);
|
var result = petService.getAllPets(null, null, null, null, pageable);
|
||||||
|
|
||||||
assertEquals(2, result.getTotalElements());
|
assertEquals(2, result.getTotalElements());
|
||||||
verify(petRepository).searchPets(null, null, null, pageable);
|
verify(petRepository).searchPets(null, null, null, null, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public class PetRequest {
|
|||||||
private Integer petAge;
|
private Integer petAge;
|
||||||
private String petStatus;
|
private String petStatus;
|
||||||
private BigDecimal petPrice;
|
private BigDecimal petPrice;
|
||||||
|
private Long customerId;
|
||||||
|
private Long storeId;
|
||||||
|
|
||||||
public PetRequest() {
|
public PetRequest() {
|
||||||
}
|
}
|
||||||
@@ -60,4 +62,20 @@ public class PetRequest {
|
|||||||
public void setPetPrice(BigDecimal petPrice) {
|
public void setPetPrice(BigDecimal petPrice) {
|
||||||
this.petPrice = petPrice;
|
this.petPrice = petPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStoreId() {
|
||||||
|
return storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreId(Long storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ public class PetResponse {
|
|||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
private Long customerId;
|
||||||
|
private String customerName;
|
||||||
|
private Long storeId;
|
||||||
|
private String storeName;
|
||||||
|
|
||||||
public PetResponse() {
|
public PetResponse() {
|
||||||
}
|
}
|
||||||
@@ -97,4 +101,36 @@ public class PetResponse {
|
|||||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomerName() {
|
||||||
|
return customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerName(String customerName) {
|
||||||
|
this.customerName = customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStoreId() {
|
||||||
|
return storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreId(Long storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStoreName() {
|
||||||
|
return storeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreName(String storeName) {
|
||||||
|
this.storeName = storeName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class PetApi {
|
|||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PetResponse> listPets(String query, String species, String status) throws Exception {
|
public List<PetResponse> listPets(String query, String species, String status, Long storeId) throws Exception {
|
||||||
String path = "/api/v1/pets?page=0&size=1000";
|
String path = "/api/v1/pets?page=0&size=1000";
|
||||||
if (query != null && !query.isEmpty()) {
|
if (query != null && !query.isEmpty()) {
|
||||||
path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8);
|
path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8);
|
||||||
@@ -35,6 +35,9 @@ public class PetApi {
|
|||||||
if (status != null && !status.isEmpty()) {
|
if (status != null && !status.isEmpty()) {
|
||||||
path += "&status=" + URLEncoder.encode(status, StandardCharsets.UTF_8);
|
path += "&status=" + URLEncoder.encode(status, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
if (storeId != null) {
|
||||||
|
path += "&storeId=" + storeId;
|
||||||
|
}
|
||||||
String response = apiClient.getRawResponse(path);
|
String response = apiClient.getRawResponse(path);
|
||||||
PageResponse<PetResponse> pageResponse = apiClient.getObjectMapper().readValue(
|
PageResponse<PetResponse> pageResponse = apiClient.getObjectMapper().readValue(
|
||||||
response,
|
response,
|
||||||
@@ -46,8 +49,12 @@ public class PetApi {
|
|||||||
return pageResponse.getContent();
|
return pageResponse.getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PetResponse> listPets(String query, String species, String status) throws Exception {
|
||||||
|
return listPets(query, species, status, null);
|
||||||
|
}
|
||||||
|
|
||||||
public List<PetResponse> listPets(String query) throws Exception {
|
public List<PetResponse> listPets(String query) throws Exception {
|
||||||
return listPets(query, null, null);
|
return listPets(query, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PetResponse createPet(PetRequest request) throws Exception {
|
public PetResponse createPet(PetRequest request) throws Exception {
|
||||||
|
|||||||
@@ -63,6 +63,12 @@ public class PetController {
|
|||||||
@FXML
|
@FXML
|
||||||
private TableColumn<Pet, String> colPetStatus;
|
private TableColumn<Pet, String> colPetStatus;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Pet, String> colCustomerName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Pet, String> colStoreName;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableView<Pet> tvPets;
|
private TableView<Pet> tvPets;
|
||||||
|
|
||||||
@@ -156,11 +162,13 @@ public class PetController {
|
|||||||
colPetAge.setCellValueFactory(new PropertyValueFactory<Pet,Integer>("petAge"));
|
colPetAge.setCellValueFactory(new PropertyValueFactory<Pet,Integer>("petAge"));
|
||||||
colPetStatus.setCellValueFactory(new PropertyValueFactory<Pet,String>("petStatus"));
|
colPetStatus.setCellValueFactory(new PropertyValueFactory<Pet,String>("petStatus"));
|
||||||
colPetPrice.setCellValueFactory(new PropertyValueFactory<Pet,Double>("petPrice"));
|
colPetPrice.setCellValueFactory(new PropertyValueFactory<Pet,Double>("petPrice"));
|
||||||
|
colCustomerName.setCellValueFactory(new PropertyValueFactory<Pet,String>("customerName"));
|
||||||
|
colStoreName.setCellValueFactory(new PropertyValueFactory<Pet,String>("storeName"));
|
||||||
configureImageColumn(colPetImage);
|
configureImageColumn(colPetImage);
|
||||||
|
|
||||||
loadSpeciesFilter();
|
loadSpeciesFilter();
|
||||||
|
|
||||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Available", "Adopted", "Pending"));
|
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Available", "Adopted", "Owned", "Pending"));
|
||||||
cbStatusFilter.getSelectionModel().selectFirst();
|
cbStatusFilter.getSelectionModel().selectFirst();
|
||||||
|
|
||||||
displayPets();
|
displayPets();
|
||||||
@@ -316,7 +324,7 @@ public class PetController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Pet mapToPet(PetResponse response) {
|
private Pet mapToPet(PetResponse response) {
|
||||||
return new Pet(
|
Pet pet = new Pet(
|
||||||
response.getPetId().intValue(),
|
response.getPetId().intValue(),
|
||||||
response.getPetName(),
|
response.getPetName(),
|
||||||
response.getPetSpecies(),
|
response.getPetSpecies(),
|
||||||
@@ -326,6 +334,11 @@ public class PetController {
|
|||||||
response.getPetPrice().doubleValue(),
|
response.getPetPrice().doubleValue(),
|
||||||
response.getImageUrl()
|
response.getImageUrl()
|
||||||
);
|
);
|
||||||
|
pet.setCustomerName(response.getCustomerName());
|
||||||
|
pet.setStoreName(response.getStoreName());
|
||||||
|
pet.setCustomerId(response.getCustomerId() != null ? response.getCustomerId() : 0L);
|
||||||
|
pet.setStoreId(response.getStoreId() != null ? response.getStoreId() : 0L);
|
||||||
|
return pet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureImageColumn(TableColumn<Pet, String> column) {
|
private void configureImageColumn(TableColumn<Pet, String> column) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.example.petshopdesktop.controllers.dialogcontrollers;
|
package org.example.petshopdesktop.controllers.dialogcontrollers;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
@@ -10,8 +11,10 @@ import javafx.scene.image.ImageView;
|
|||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.example.petshopdesktop.Validator;
|
import org.example.petshopdesktop.Validator;
|
||||||
|
import org.example.petshopdesktop.api.dto.common.DropdownOption;
|
||||||
import org.example.petshopdesktop.api.dto.pet.PetRequest;
|
import org.example.petshopdesktop.api.dto.pet.PetRequest;
|
||||||
import org.example.petshopdesktop.api.dto.pet.PetResponse;
|
import org.example.petshopdesktop.api.dto.pet.PetResponse;
|
||||||
|
import org.example.petshopdesktop.api.endpoints.DropdownApi;
|
||||||
import org.example.petshopdesktop.api.endpoints.PetApi;
|
import org.example.petshopdesktop.api.endpoints.PetApi;
|
||||||
import org.example.petshopdesktop.models.Pet;
|
import org.example.petshopdesktop.models.Pet;
|
||||||
import org.example.petshopdesktop.util.ActivityLogger;
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
@@ -20,6 +23,7 @@ import org.example.petshopdesktop.util.FilePickerSupport;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PetDialogController {
|
public class PetDialogController {
|
||||||
|
|
||||||
@@ -38,6 +42,12 @@ public class PetDialogController {
|
|||||||
@FXML
|
@FXML
|
||||||
private ComboBox<String> cbPetStatus;
|
private ComboBox<String> cbPetStatus;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<DropdownOption> cbCustomer;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<DropdownOption> cbStore;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label lblMode;
|
private Label lblMode;
|
||||||
|
|
||||||
@@ -70,16 +80,54 @@ public class PetDialogController {
|
|||||||
private String currentImageUrl;
|
private String currentImageUrl;
|
||||||
private boolean removeImageRequested;
|
private boolean removeImageRequested;
|
||||||
|
|
||||||
|
private Long pendingCustomerId = null;
|
||||||
|
private Long pendingStoreId = null;
|
||||||
|
|
||||||
private ObservableList<String> statusList = FXCollections.observableArrayList(
|
private ObservableList<String> statusList = FXCollections.observableArrayList(
|
||||||
"Available", "Adopted"
|
"Available", "Adopted", "Owned"
|
||||||
);
|
);
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void initialize() {
|
void initialize() {
|
||||||
|
|
||||||
cbPetStatus.setItems(statusList); //set status combobox
|
cbPetStatus.setItems(statusList);
|
||||||
|
|
||||||
|
cbCustomer.setCellFactory(param -> new ListCell<>() {
|
||||||
|
@Override protected void updateItem(DropdownOption o, boolean empty) {
|
||||||
|
super.updateItem(o, empty);
|
||||||
|
setText(empty || o == null ? null : o.getLabel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cbCustomer.setButtonCell(new ListCell<>() {
|
||||||
|
@Override protected void updateItem(DropdownOption o, boolean empty) {
|
||||||
|
super.updateItem(o, empty);
|
||||||
|
setText(empty || o == null ? null : o.getLabel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cbStore.setCellFactory(param -> new ListCell<>() {
|
||||||
|
@Override protected void updateItem(DropdownOption o, boolean empty) {
|
||||||
|
super.updateItem(o, empty);
|
||||||
|
setText(empty || o == null ? null : o.getLabel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cbStore.setButtonCell(new ListCell<>() {
|
||||||
|
@Override protected void updateItem(DropdownOption o, boolean empty) {
|
||||||
|
super.updateItem(o, empty);
|
||||||
|
setText(empty || o == null ? null : o.getLabel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cbCustomer.setVisible(false);
|
||||||
|
cbStore.setVisible(false);
|
||||||
|
|
||||||
|
cbPetStatus.valueProperty().addListener((obs, oldVal, newVal) -> {
|
||||||
|
boolean isOwned = "Owned".equalsIgnoreCase(newVal);
|
||||||
|
boolean isAvailable = "Available".equalsIgnoreCase(newVal) || "Unadopted".equalsIgnoreCase(newVal);
|
||||||
|
cbCustomer.setVisible(isOwned);
|
||||||
|
cbStore.setVisible(isAvailable);
|
||||||
|
});
|
||||||
|
|
||||||
//Set up mouse handlers for buttons
|
|
||||||
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MouseEvent mouseEvent) {
|
public void handle(MouseEvent mouseEvent) {
|
||||||
@@ -97,6 +145,9 @@ public class PetDialogController {
|
|||||||
btnChangeImage.setOnMouseClicked(mouseEvent -> handleChangeImage());
|
btnChangeImage.setOnMouseClicked(mouseEvent -> handleChangeImage());
|
||||||
btnRemoveImage.setOnMouseClicked(mouseEvent -> handleRemoveImage());
|
btnRemoveImage.setOnMouseClicked(mouseEvent -> handleRemoveImage());
|
||||||
refreshImagePreview();
|
refreshImagePreview();
|
||||||
|
|
||||||
|
loadCustomers();
|
||||||
|
loadStores();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buttonSaveClicked(MouseEvent mouseEvent) {
|
private void buttonSaveClicked(MouseEvent mouseEvent) {
|
||||||
@@ -111,6 +162,10 @@ public class PetDialogController {
|
|||||||
if (cbPetStatus.getSelectionModel().getSelectedItem() == null){
|
if (cbPetStatus.getSelectionModel().getSelectedItem() == null){
|
||||||
errorMsg += "Status is required";
|
errorMsg += "Status is required";
|
||||||
}
|
}
|
||||||
|
String selectedStatus = cbPetStatus.getValue();
|
||||||
|
if ("Owned".equalsIgnoreCase(selectedStatus) && cbCustomer.getValue() == null) {
|
||||||
|
errorMsg += "Customer is required for Owned status\n";
|
||||||
|
}
|
||||||
|
|
||||||
//Check validation (length size)
|
//Check validation (length size)
|
||||||
errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50);
|
errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50);
|
||||||
@@ -184,9 +239,81 @@ public class PetDialogController {
|
|||||||
}
|
}
|
||||||
request.setPetAge(age);
|
request.setPetAge(age);
|
||||||
|
|
||||||
|
String status = cbPetStatus.getValue();
|
||||||
|
if ("Owned".equalsIgnoreCase(status) && cbCustomer.getValue() != null) {
|
||||||
|
request.setCustomerId(cbCustomer.getValue().getId());
|
||||||
|
}
|
||||||
|
if (("Available".equalsIgnoreCase(status) || "Unadopted".equalsIgnoreCase(status)) && cbStore.getValue() != null) {
|
||||||
|
request.setStoreId(cbStore.getValue().getId());
|
||||||
|
}
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadCustomers() {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
List<DropdownOption> customers = DropdownApi.getInstance().getCustomers();
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbCustomer.setItems(FXCollections.observableArrayList(customers));
|
||||||
|
applySelectedCustomer();
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetDialogController.loadCustomers", e, "Loading customers");
|
||||||
|
cbCustomer.setDisable(true);
|
||||||
|
cbCustomer.setPromptText("Unable to load customers");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStores() {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbStore.setItems(FXCollections.observableArrayList(stores));
|
||||||
|
applySelectedStore();
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetDialogController.loadStores", e, "Loading stores");
|
||||||
|
cbStore.setDisable(true);
|
||||||
|
cbStore.setPromptText("Unable to load stores");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySelectedCustomer() {
|
||||||
|
if (pendingCustomerId == null) return;
|
||||||
|
DropdownOption selected = findOptionById(cbCustomer.getItems(), pendingCustomerId);
|
||||||
|
if (selected != null) {
|
||||||
|
cbCustomer.setValue(selected);
|
||||||
|
pendingCustomerId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySelectedStore() {
|
||||||
|
if (pendingStoreId == null) return;
|
||||||
|
DropdownOption selected = findOptionById(cbStore.getItems(), pendingStoreId);
|
||||||
|
if (selected != null) {
|
||||||
|
cbStore.setValue(selected);
|
||||||
|
pendingStoreId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DropdownOption findOptionById(List<DropdownOption> options, Long id) {
|
||||||
|
if (id == null || options == null) return null;
|
||||||
|
for (DropdownOption option : options) {
|
||||||
|
if (option.getId() != null && option.getId().equals(id)) return option;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void closeStage(MouseEvent mouseEvent) {
|
private void closeStage(MouseEvent mouseEvent) {
|
||||||
Node node = (Node) mouseEvent.getSource();
|
Node node = (Node) mouseEvent.getSource();
|
||||||
Stage stage = (Stage) node.getScene().getWindow();
|
Stage stage = (Stage) node.getScene().getWindow();
|
||||||
@@ -206,14 +333,14 @@ public class PetDialogController {
|
|||||||
removeImageRequested = false;
|
removeImageRequested = false;
|
||||||
refreshImagePreview();
|
refreshImagePreview();
|
||||||
|
|
||||||
//get the right combobox selection
|
pendingCustomerId = pet.getCustomerId() > 0 ? pet.getCustomerId() : null;
|
||||||
|
pendingStoreId = pet.getStoreId() > 0 ? pet.getStoreId() : null;
|
||||||
|
|
||||||
for (String status : cbPetStatus.getItems()) {
|
for (String status : cbPetStatus.getItems()) {
|
||||||
if(status.equals(pet.getPetStatus())){
|
if(status.equals(pet.getPetStatus())){
|
||||||
cbPetStatus.getSelectionModel().select(status);
|
cbPetStatus.getSelectionModel().select(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ public class Pet {
|
|||||||
private SimpleStringProperty petStatus;
|
private SimpleStringProperty petStatus;
|
||||||
private SimpleDoubleProperty petPrice;
|
private SimpleDoubleProperty petPrice;
|
||||||
private SimpleStringProperty imageUrl;
|
private SimpleStringProperty imageUrl;
|
||||||
|
private SimpleStringProperty customerName = new SimpleStringProperty("");
|
||||||
|
private SimpleStringProperty storeName = new SimpleStringProperty("");
|
||||||
|
private long customerId = 0L;
|
||||||
|
private long storeId = 0L;
|
||||||
|
|
||||||
public Pet(int petId, String petName, String petSpecies, String petBreed, int petAge, String petStatus, double petPrice, String imageUrl) {
|
public Pet(int petId, String petName, String petSpecies, String petBreed, int petAge, String petStatus, double petPrice, String imageUrl) {
|
||||||
this.petId = new SimpleIntegerProperty(petId);
|
this.petId = new SimpleIntegerProperty(petId);
|
||||||
@@ -120,4 +124,44 @@ public class Pet {
|
|||||||
public SimpleStringProperty imageUrlProperty() {
|
public SimpleStringProperty imageUrlProperty() {
|
||||||
return imageUrl;
|
return imageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCustomerName() {
|
||||||
|
return customerName.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerName(String customerName) {
|
||||||
|
this.customerName.set(customerName != null ? customerName : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleStringProperty customerNameProperty() {
|
||||||
|
return customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStoreName() {
|
||||||
|
return storeName.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreName(String storeName) {
|
||||||
|
this.storeName.set(storeName != null ? storeName : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleStringProperty storeNameProperty() {
|
||||||
|
return storeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStoreId() {
|
||||||
|
return storeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreId(long storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="560.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogController">
|
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="660.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogController">
|
||||||
<children>
|
<children>
|
||||||
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
|
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
|
||||||
<children>
|
<children>
|
||||||
@@ -153,6 +153,34 @@
|
|||||||
</TextField>
|
</TextField>
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="3">
|
||||||
|
<children>
|
||||||
|
<Label text="Customer:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<ComboBox fx:id="cbCustomer" prefHeight="29.0" prefWidth="336.0" promptText="Select Customer" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
|
||||||
|
</padding>
|
||||||
|
</ComboBox>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
|
||||||
|
<children>
|
||||||
|
<Label text="Store:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<ComboBox fx:id="cbStore" prefHeight="29.0" prefWidth="336.0" promptText="Select Store" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
|
||||||
|
</padding>
|
||||||
|
</ComboBox>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
</children>
|
</children>
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
||||||
|
|||||||
@@ -79,6 +79,8 @@
|
|||||||
<TableColumn fx:id="colPetAge" prefWidth="60.0" text="Age" />
|
<TableColumn fx:id="colPetAge" prefWidth="60.0" text="Age" />
|
||||||
<TableColumn fx:id="colPetStatus" prefWidth="110.0" text="Status" />
|
<TableColumn fx:id="colPetStatus" prefWidth="110.0" text="Status" />
|
||||||
<TableColumn fx:id="colPetPrice" prefWidth="80.0" text="Price" />
|
<TableColumn fx:id="colPetPrice" prefWidth="80.0" text="Price" />
|
||||||
|
<TableColumn fx:id="colCustomerName" prefWidth="130.0" text="Owner" />
|
||||||
|
<TableColumn fx:id="colStoreName" prefWidth="130.0" text="Store" />
|
||||||
</columns>
|
</columns>
|
||||||
</TableView>
|
</TableView>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
Reference in New Issue
Block a user