fixed creating adoption for the backend and implemented adoption to andriod for changes

This commit is contained in:
Alex
2026-04-07 07:27:37 -06:00
parent 0a55014f21
commit b4c1175ee1
7 changed files with 105 additions and 36 deletions

View File

@@ -57,7 +57,7 @@ public class AdoptionAdapter extends RecyclerView.Adapter<AdoptionAdapter.Adopti
holder.tvStatus.setText(status); holder.tvStatus.setText(status);
switch (status) { switch (status) {
case "Approved": case "Completed":
holder.tvStatus.setBackgroundColor(Color.parseColor("#4CAF50")); holder.tvStatus.setBackgroundColor(Color.parseColor("#4CAF50"));
break; break;
case "Pending": case "Pending":

View File

@@ -10,20 +10,27 @@ public class AdoptionDTO {
private String customerName; private String customerName;
private Long employeeId; private Long employeeId;
private String employeeName; private String employeeName;
private Long sourceStoreId;
private String sourceStoreName;
private String adoptionDate; private String adoptionDate;
private String adoptionStatus; private String adoptionStatus;
private BigDecimal adoptionFee; private BigDecimal adoptionFee;
private String createdAt; private String createdAt;
private String updatedAt; private String updatedAt;
public AdoptionDTO(Long petId, Long customerId, String adoptionDate, String adoptionStatus) { public AdoptionDTO(Long petId, Long customerId, Long sourceStoreId, String adoptionDate, String adoptionStatus) {
this(petId, customerId, null, adoptionDate, adoptionStatus); this.petId = petId;
this.customerId = customerId;
this.sourceStoreId = sourceStoreId;
this.adoptionDate = adoptionDate;
this.adoptionStatus = adoptionStatus;
} }
public AdoptionDTO(Long petId, Long customerId, Long employeeId, String adoptionDate, String adoptionStatus) { public AdoptionDTO(Long petId, Long customerId, Long employeeId, Long sourceStoreId, String adoptionDate, String adoptionStatus) {
this.petId = petId; this.petId = petId;
this.customerId = customerId; this.customerId = customerId;
this.employeeId = employeeId; this.employeeId = employeeId;
this.sourceStoreId = sourceStoreId;
this.adoptionDate = adoptionDate; this.adoptionDate = adoptionDate;
this.adoptionStatus = adoptionStatus; this.adoptionStatus = adoptionStatus;
} }
@@ -56,6 +63,14 @@ public class AdoptionDTO {
return employeeName; return employeeName;
} }
public Long getSourceStoreId() {
return sourceStoreId;
}
public String getSourceStoreName() {
return sourceStoreName;
}
public String getAdoptionDate() { public String getAdoptionDate() {
return adoptionDate; return adoptionDate;
} }

View File

@@ -18,6 +18,7 @@ import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.viewmodels.AdoptionViewModel; import com.example.petstoremobile.viewmodels.AdoptionViewModel;
import com.example.petstoremobile.viewmodels.CustomerViewModel; import com.example.petstoremobile.viewmodels.CustomerViewModel;
import com.example.petstoremobile.viewmodels.PetViewModel; import com.example.petstoremobile.viewmodels.PetViewModel;
import com.example.petstoremobile.viewmodels.StoreViewModel;
import java.util.*; import java.util.*;
@@ -35,15 +36,18 @@ public class AdoptionDetailFragment extends Fragment {
private boolean isEditing = false; private boolean isEditing = false;
private long preselectedPetId = -1; private long preselectedPetId = -1;
private long preselectedCustomerId = -1; private long preselectedCustomerId = -1;
private long preselectedStoreId = -1;
private List<PetDTO> petList = new ArrayList<>(); private List<PetDTO> petList = new ArrayList<>();
private List<CustomerDTO> customerList = new ArrayList<>(); private List<CustomerDTO> customerList = new ArrayList<>();
private List<StoreDTO> storeList = new ArrayList<>();
private final String[] STATUSES = {"Pending", "Approved", "Rejected"}; private final String[] STATUSES = {"Pending", "Completed", "Cancelled"};
private AdoptionViewModel adoptionViewModel; private AdoptionViewModel adoptionViewModel;
private PetViewModel petViewModel; private PetViewModel petViewModel;
private CustomerViewModel customerViewModel; private CustomerViewModel customerViewModel;
private StoreViewModel storeViewModel;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@@ -51,6 +55,7 @@ public class AdoptionDetailFragment extends Fragment {
adoptionViewModel = new ViewModelProvider(this).get(AdoptionViewModel.class); adoptionViewModel = new ViewModelProvider(this).get(AdoptionViewModel.class);
petViewModel = new ViewModelProvider(this).get(PetViewModel.class); petViewModel = new ViewModelProvider(this).get(PetViewModel.class);
customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class); customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class);
storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class);
} }
@Override @Override
@@ -107,6 +112,7 @@ public class AdoptionDetailFragment extends Fragment {
private void loadSpinnersData() { private void loadSpinnersData() {
loadPets(); loadPets();
loadCustomers(); loadCustomers();
loadStores();
} }
/** /**
@@ -152,6 +158,27 @@ public class AdoptionDetailFragment extends Fragment {
preselectedCustomerId, CustomerDTO::getCustomerId); preselectedCustomerId, CustomerDTO::getCustomerId);
} }
/**
* Loads the list of stores from the API.
*/
private void loadStores() {
storeViewModel.getAllStores(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
storeList = resource.data.getContent();
refreshStoreSpinner();
}
});
}
/**
* Populates the store selection spinner with data.
*/
private void refreshStoreSpinner() {
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionStore, storeList,
StoreDTO::getStoreName, "-- Select Store --",
preselectedStoreId, StoreDTO::getStoreId);
}
/** /**
* Handles arguments to determine if the fragment is in edit or add mode. * Handles arguments to determine if the fragment is in edit or add mode.
*/ */
@@ -182,11 +209,13 @@ public class AdoptionDetailFragment extends Fragment {
AdoptionDTO a = resource.data; AdoptionDTO a = resource.data;
preselectedPetId = a.getPetId() != null ? a.getPetId() : -1; preselectedPetId = a.getPetId() != null ? a.getPetId() : -1;
preselectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1; preselectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1;
preselectedStoreId = a.getSourceStoreId() != null ? a.getSourceStoreId() : -1;
binding.etAdoptionDate.setText(a.getAdoptionDate()); binding.etAdoptionDate.setText(a.getAdoptionDate());
SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, a.getAdoptionStatus()); SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, a.getAdoptionStatus());
refreshPetSpinner(); refreshPetSpinner();
refreshCustomerSpinner(); refreshCustomerSpinner();
refreshStoreSpinner();
} else if (resource.status == Resource.Status.ERROR) { } else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Failed to load adoption: " + resource.message, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Failed to load adoption: " + resource.message, Toast.LENGTH_SHORT).show();
} }
@@ -203,6 +232,9 @@ public class AdoptionDetailFragment extends Fragment {
if (binding.spinnerAdoptionPet.getSelectedItemPosition() == 0) { if (binding.spinnerAdoptionPet.getSelectedItemPosition() == 0) {
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return; Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
} }
if (binding.spinnerAdoptionStore.getSelectedItemPosition() == 0) {
Toast.makeText(getContext(), "Select a store", Toast.LENGTH_SHORT).show(); return;
}
String date = binding.etAdoptionDate.getText().toString().trim(); String date = binding.etAdoptionDate.getText().toString().trim();
if (date.isEmpty()) { if (date.isEmpty()) {
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return; Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
@@ -210,11 +242,13 @@ public class AdoptionDetailFragment extends Fragment {
CustomerDTO customer = customerList.get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1); CustomerDTO customer = customerList.get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
PetDTO pet = petList.get(binding.spinnerAdoptionPet.getSelectedItemPosition() - 1); PetDTO pet = petList.get(binding.spinnerAdoptionPet.getSelectedItemPosition() - 1);
StoreDTO store = storeList.get(binding.spinnerAdoptionStore.getSelectedItemPosition() - 1);
String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()]; String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()];
AdoptionDTO dto = new AdoptionDTO( AdoptionDTO dto = new AdoptionDTO(
pet.getPetId(), pet.getPetId(),
customer.getCustomerId(), customer.getCustomerId(),
store.getStoreId(),
date, date,
status status
); );

View File

@@ -95,6 +95,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Source Store"
android:textColor="@color/text_dark"
android:textSize="12sp"
android:layout_marginBottom="4dp"/>
<Spinner
android:id="@+id/spinnerAdoptionStore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"/>
<!-- Adoption Date --> <!-- Adoption Date -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -165,4 +179,4 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -33,6 +33,8 @@ public class AdoptionController {
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')") @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,
@RequestParam(required = false) Long customerId,
@RequestParam(required = false) String status,
Pageable pageable) { Pageable pageable) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String role = authentication.getAuthorities().stream() String role = authentication.getAuthorities().stream()
@@ -40,13 +42,13 @@ public class AdoptionController {
.map(authority -> authority.getAuthority().replace("ROLE_", "")) .map(authority -> authority.getAuthority().replace("ROLE_", ""))
.orElse(null); .orElse(null);
Long customerId = null; Long effectiveCustomerId = customerId;
if (role != null && role.equals("CUSTOMER")) { if (role != null && role.equals("CUSTOMER")) {
User user = AuthenticationHelper.getAuthenticatedUser(userRepository); User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
customerId = user.getId(); effectiveCustomerId = user.getId();
} }
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, pageable, customerId)); return ResponseEntity.ok(adoptionService.getAllAdoptions(q, effectiveCustomerId, status, pageable));
} }
@GetMapping("/{id}") @GetMapping("/{id}")

View File

@@ -14,22 +14,24 @@ import java.util.Optional;
public interface AdoptionRepository extends JpaRepository<Adoption, Long> { public interface AdoptionRepository extends JpaRepository<Adoption, Long> {
@Query("SELECT a FROM Adoption a WHERE " + @Query("SELECT a FROM Adoption a WHERE " +
"(:q IS NULL OR (" +
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"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); ")) AND " +
"(:customerId IS NULL OR a.customer.id = :customerId) AND " +
Page<Adoption> findByCustomerId(Long customerId, Pageable pageable); "(:status IS NULL OR LOWER(a.adoptionStatus) = LOWER(:status))")
Page<Adoption> searchAdoptions(
@Query("SELECT a FROM Adoption a WHERE a.customer.id = :customerId AND (" + @Param("q") String query,
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + @Param("customerId") Long customerId,
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + @Param("status") String status,
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%')))") Pageable pageable);
Page<Adoption> searchAdoptionsByCustomer(@Param("customerId") Long customerId, @Param("q") String query, Pageable pageable);
Optional<Adoption> findFirstByPet_IdAndAdoptionStatusOrderByAdoptionDateDesc(Long petId, String adoptionStatus); Optional<Adoption> findFirstByPet_IdAndAdoptionStatusOrderByAdoptionDateDesc(Long petId, String adoptionStatus);
boolean existsByPetPetIdAndAdoptionStatusIgnoreCaseAndAdoptionIdNot(Long petId, String adoptionStatus, Long adoptionId); @Query("SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Adoption a WHERE a.pet.id = :petId AND LOWER(a.adoptionStatus) = LOWER(:adoptionStatus) AND a.adoptionId <> :adoptionId")
boolean existsByPetPetIdAndAdoptionStatusIgnoreCaseAndAdoptionIdNot(@Param("petId") Long petId, @Param("adoptionStatus") String adoptionStatus, @Param("adoptionId") Long adoptionId);
boolean existsByPetPetIdAndAdoptionStatusIgnoreCase(Long petId, String adoptionStatus); @Query("SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Adoption a WHERE a.pet.id = :petId AND LOWER(a.adoptionStatus) = LOWER(:adoptionStatus)")
boolean existsByPetPetIdAndAdoptionStatusIgnoreCase(@Param("petId") Long petId, @Param("adoptionStatus") String adoptionStatus);
} }

View File

@@ -38,22 +38,16 @@ public class AdoptionService {
this.storeRepository = storeRepository; this.storeRepository = storeRepository;
} }
public Page<AdoptionResponse> getAllAdoptions(String query, Pageable pageable, Long customerId) { public Page<AdoptionResponse> getAllAdoptions(String query, Long customerId, String status, Pageable pageable) {
Page<Adoption> adoptions; String normalizedQuery = normalizeFilter(query);
String normalizedStatus = normalizeFilter(status);
if (customerId != null) { Page<Adoption> adoptions = adoptionRepository.searchAdoptions(
if (query != null && !query.trim().isEmpty()) { normalizedQuery,
adoptions = adoptionRepository.searchAdoptionsByCustomer(customerId, query, pageable); customerId,
} else { normalizedStatus,
adoptions = adoptionRepository.findByCustomerId(customerId, pageable); pageable
} );
} else {
if (query != null && !query.trim().isEmpty()) {
adoptions = adoptionRepository.searchAdoptions(query, pageable);
} else {
adoptions = adoptionRepository.findAll(pageable);
}
}
return adoptions.map(this::mapToResponse); return adoptions.map(this::mapToResponse);
} }
@@ -140,6 +134,14 @@ public class AdoptionService {
adoptionRepository.deleteAllById(request.getIds()); adoptionRepository.deleteAllById(request.getIds());
} }
private String normalizeFilter(String value) {
if (value == null) {
return null;
}
String trimmed = value.trim();
return trimmed.isEmpty() ? null : trimmed;
}
private AdoptionResponse mapToResponse(Adoption adoption) { private AdoptionResponse mapToResponse(Adoption adoption) {
StoreLocation sourceStore = adoption.getSourceStore(); StoreLocation sourceStore = adoption.getSourceStore();
return new AdoptionResponse( return new AdoptionResponse(