diff --git a/android/app/src/main/java/com/example/petstoremobile/adapters/AdoptionAdapter.java b/android/app/src/main/java/com/example/petstoremobile/adapters/AdoptionAdapter.java index c6bd678c..5ee0adb3 100644 --- a/android/app/src/main/java/com/example/petstoremobile/adapters/AdoptionAdapter.java +++ b/android/app/src/main/java/com/example/petstoremobile/adapters/AdoptionAdapter.java @@ -24,13 +24,14 @@ public class AdoptionAdapter extends RecyclerView.Adapter petNames; private List petIds; + private String createdAt; private String updatedAt; + + // Constructor for CREATE/UPDATE request body // Matches AppointmentRequest exactly public AppointmentDTO(Long customerId, Long storeId, Long serviceId, @@ -32,62 +38,79 @@ public class AppointmentDTO { this.appointmentTime = appointmentTime; this.appointmentStatus = appointmentStatus; this.petIds = petIds; + this.employeeId = employeeId; } // Getters public Long getAppointmentId() { + return appointmentId; } public Long getCustomerId() { + return customerId; } public String getCustomerName() { + return customerName; } public Long getStoreId() { + return storeId; } public String getStoreName() { + return storeName; } public Long getServiceId() { + return serviceId; } public String getServiceName() { + return serviceName; } public String getAppointmentDate() { + return appointmentDate; } public String getAppointmentTime() { + return appointmentTime; } public String getAppointmentStatus() { + return appointmentStatus; } public List getPetNames() { + return petNames; } public List getPetIds() { + return petIds; } + + public String getCreatedAt() { + return createdAt; } public String getUpdatedAt() { + return updatedAt; } @@ -97,10 +120,12 @@ public class AppointmentDTO { } public Long getPetID() { + return (petIds != null && !petIds.isEmpty()) ? petIds.get(0) : null; } public Long getPetId() { + return getPetID(); } @@ -110,11 +135,20 @@ public class AppointmentDTO { } public Long getServiceID() { + return serviceId; } + public String getEmployeeName() { + + return employeeName; + } + // Status alias public String getStatus() { + return appointmentStatus; } + + } diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java index 34e7d602..0c78284d 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java @@ -129,7 +129,8 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop args.putLong("customerId", a.getCustomerId() != null ? a.getCustomerId() : -1); args.putString("adoptionDate", a.getAdoptionDate()); args.putString("adoptionStatus", a.getAdoptionStatus()); - } + if (a.getEmployeeId() != null) + args.putLong("employeeId", a.getEmployeeId());} detail.setArguments(args); ListFragment lf = (ListFragment) getParentFragment(); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java index c32edaf0..0b38920c 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java @@ -19,7 +19,7 @@ public class AdoptionDetailFragment extends Fragment { private TextView tvMode, tvAdoptionId; private EditText etAdoptionDate; - private Spinner spinnerPet, spinnerCustomer, spinnerStatus; + private Spinner spinnerPet, spinnerCustomer, spinnerEmployee, spinnerStatus; private Button btnSave, btnDelete, btnBack; private long adoptionId = -1; @@ -27,6 +27,9 @@ public class AdoptionDetailFragment extends Fragment { private long preselectedPetId = -1; private long preselectedCustomerId = -1; + private List employeeList = new ArrayList<>(); + private long preselectedEmployeeId = -1; + private List petList = new ArrayList<>(); private List customerList = new ArrayList<>(); @@ -54,6 +57,7 @@ public class AdoptionDetailFragment extends Fragment { etAdoptionDate = v.findViewById(R.id.etAdoptionDate); spinnerPet = v.findViewById(R.id.spinnerAdoptionPet); spinnerCustomer= v.findViewById(R.id.spinnerAdoptionCustomer); + spinnerEmployee = v.findViewById(R.id.spinnerAdoptionEmployee); spinnerStatus = v.findViewById(R.id.spinnerAdoptionStatus); btnSave = v.findViewById(R.id.btnSaveAdoption); btnDelete = v.findViewById(R.id.btnDeleteAdoption); @@ -80,6 +84,7 @@ public class AdoptionDetailFragment extends Fragment { private void loadData() { loadPets(); loadCustomers(); + loadEmployees(); } private void loadPets() { @@ -145,6 +150,34 @@ public class AdoptionDetailFragment extends Fragment { } } + private void loadEmployees() { + RetrofitClient.getEmployeeApi(requireContext()).getAllEmployees(0, 100) + .enqueue(new Callback>() { + public void onResponse(Call> c, + Response> r) { + if (r.isSuccessful() && r.body() != null) { + employeeList = r.body().getContent(); + List names = new ArrayList<>(); + names.add("-- Select Employee --"); + for (EmployeeDTO e : employeeList) + names.add(e.getFullName() + " (" + e.getRole() + ")"); + spinnerEmployee.setAdapter(new ArrayAdapter<>(requireContext(), + android.R.layout.simple_spinner_item, names)); + if (preselectedEmployeeId != -1) { + for (int i = 0; i < employeeList.size(); i++) { + if (employeeList.get(i).getEmployeeId() == preselectedEmployeeId) { + spinnerEmployee.setSelection(i + 1); break; + } + } + } + } + } + public void onFailure(Call> c, Throwable t) { + Log.e("ADOPTION", "Employee load failed: " + t.getMessage()); + } + }); + } + private void handleArguments() { Bundle a = getArguments(); if (a != null && a.containsKey("adoptionId")) { @@ -152,7 +185,7 @@ public class AdoptionDetailFragment extends Fragment { adoptionId = a.getLong("adoptionId"); preselectedPetId = a.getLong("petId", -1); preselectedCustomerId = a.getLong("customerId", -1); - + preselectedEmployeeId = a.getLong("employeeId", -1); tvMode.setText("Edit Adoption"); tvAdoptionId.setText("ID: " + adoptionId); tvAdoptionId.setVisibility(View.VISIBLE); @@ -180,6 +213,12 @@ public class AdoptionDetailFragment extends Fragment { if (spinnerPet.getSelectedItemPosition() == 0) { Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return; } + Long employeeId = null; + if (spinnerEmployee.getSelectedItemPosition() > 0) { + employeeId = employeeList + .get(spinnerEmployee.getSelectedItemPosition() - 1) + .getEmployeeId(); + } String date = etAdoptionDate.getText().toString().trim(); if (date.isEmpty()) { Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return; @@ -193,7 +232,8 @@ public class AdoptionDetailFragment extends Fragment { pet.getPetId(), customer.getCustomerId(), date, - status + status, + employeeId ); Log.d("ADOPTION_SAVE", "petId=" + pet.getPetId() diff --git a/android/app/src/main/res/layout/fragment_adoption_detail.xml b/android/app/src/main/res/layout/fragment_adoption_detail.xml index 2f6b153f..afe70e2b 100644 --- a/android/app/src/main/res/layout/fragment_adoption_detail.xml +++ b/android/app/src/main/res/layout/fragment_adoption_detail.xml @@ -80,6 +80,21 @@ android:layout_height="wrap_content" android:layout_marginBottom="16dp"/> + + + + + + + + + petIds; + // @NotNull(message = "Employee ID is required") + private Long employeeId; + public Long getCustomerId() { return customerId; } @@ -85,6 +88,14 @@ public class AppointmentRequest { this.petIds = petIds; } + public Long getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(Long employeeId) { + this.employeeId = employeeId; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/backend/src/main/java/com/petshop/backend/dto/appointment/AppointmentResponse.java b/backend/src/main/java/com/petshop/backend/dto/appointment/AppointmentResponse.java index c7d2e8d7..07942e84 100644 --- a/backend/src/main/java/com/petshop/backend/dto/appointment/AppointmentResponse.java +++ b/backend/src/main/java/com/petshop/backend/dto/appointment/AppointmentResponse.java @@ -14,6 +14,8 @@ public class AppointmentResponse { private String storeName; private Long serviceId; private String serviceName; + private Long employeeId; + private String employeeName; private LocalDate appointmentDate; private LocalTime appointmentTime; private String appointmentStatus; @@ -25,7 +27,11 @@ public class AppointmentResponse { public AppointmentResponse() { } - public AppointmentResponse(Long appointmentId, Long customerId, String customerName, Long storeId, String storeName, Long serviceId, String serviceName, LocalDate appointmentDate, LocalTime appointmentTime, String appointmentStatus, List petNames, List petIds, LocalDateTime createdAt, LocalDateTime updatedAt) { + public AppointmentResponse(Long appointmentId, Long customerId, String customerName, + Long storeId, String storeName, Long serviceId, String serviceName, + LocalDate appointmentDate, LocalTime appointmentTime, String appointmentStatus, + List petNames, List petIds, LocalDateTime createdAt, + LocalDateTime updatedAt, Long employeeId, String employeeName) { this.appointmentId = appointmentId; this.customerId = customerId; this.customerName = customerName; @@ -40,8 +46,9 @@ public class AppointmentResponse { this.petIds = petIds; this.createdAt = createdAt; this.updatedAt = updatedAt; + this.employeeId = employeeId; + this.employeeName = employeeName; } - public Long getAppointmentId() { return appointmentId; } @@ -98,14 +105,29 @@ public class AppointmentResponse { this.serviceName = serviceName; } + + public String getEmployeeName() { + return employeeName; + } + public void setEmployeeName(String employeeName) { + this.employeeName = employeeName; + } + public LocalDate getAppointmentDate() { return appointmentDate; } + + + + + public void setAppointmentDate(LocalDate appointmentDate) { this.appointmentDate = appointmentDate; } + + public LocalTime getAppointmentTime() { return appointmentTime; } diff --git a/backend/src/main/java/com/petshop/backend/entity/Adoption.java b/backend/src/main/java/com/petshop/backend/entity/Adoption.java index 84912ba9..7ad79d5a 100644 --- a/backend/src/main/java/com/petshop/backend/entity/Adoption.java +++ b/backend/src/main/java/com/petshop/backend/entity/Adoption.java @@ -25,6 +25,9 @@ public class Adoption { @JoinColumn(name = "customerId", nullable = false) private Customer customer; + @ManyToOne + private Employee employee; + @Column(nullable = false) private LocalDate adoptionDate; @@ -76,6 +79,14 @@ public class Adoption { this.customer = customer; } + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } + public LocalDate getAdoptionDate() { return adoptionDate; } @@ -133,4 +144,7 @@ public class Adoption { ", updatedAt=" + updatedAt + '}'; } + + public void setEmployeeName(String s) { + } } diff --git a/backend/src/main/java/com/petshop/backend/entity/Appointment.java b/backend/src/main/java/com/petshop/backend/entity/Appointment.java index 101ff885..7e79cbe5 100644 --- a/backend/src/main/java/com/petshop/backend/entity/Appointment.java +++ b/backend/src/main/java/com/petshop/backend/entity/Appointment.java @@ -31,6 +31,10 @@ public class Appointment { @JoinColumn(name = "serviceId", nullable = false) private Service service; + @ManyToOne + @JoinColumn(name = "employeeId") + private Employee employee; + @Column(nullable = false) private LocalDate appointmentDate; @@ -104,6 +108,14 @@ public class Appointment { this.service = service; } + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } + public LocalDate getAppointmentDate() { return appointmentDate; } diff --git a/backend/src/main/java/com/petshop/backend/service/AdoptionService.java b/backend/src/main/java/com/petshop/backend/service/AdoptionService.java index a8f7f476..b7df634c 100644 --- a/backend/src/main/java/com/petshop/backend/service/AdoptionService.java +++ b/backend/src/main/java/com/petshop/backend/service/AdoptionService.java @@ -5,6 +5,7 @@ import com.petshop.backend.dto.adoption.AdoptionResponse; import com.petshop.backend.dto.common.BulkDeleteRequest; import com.petshop.backend.entity.Adoption; import com.petshop.backend.entity.Customer; +import com.petshop.backend.entity.Employee; import com.petshop.backend.entity.Pet; import com.petshop.backend.exception.ResourceNotFoundException; import com.petshop.backend.repository.AdoptionRepository; @@ -14,6 +15,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.petshop.backend.repository.EmployeeRepository; @Service public class AdoptionService { @@ -21,11 +23,15 @@ public class AdoptionService { private final AdoptionRepository adoptionRepository; private final PetRepository petRepository; private final CustomerRepository customerRepository; + private final EmployeeRepository employeeRepository; + private Adoption response; - public AdoptionService(AdoptionRepository adoptionRepository, PetRepository petRepository, CustomerRepository customerRepository) { + public AdoptionService(AdoptionRepository adoptionRepository, PetRepository petRepository, CustomerRepository customerRepository, EmployeeRepository employeeRepository) { this.adoptionRepository = adoptionRepository; this.petRepository = petRepository; this.customerRepository = customerRepository; + this.employeeRepository = employeeRepository; + } public Page getAllAdoptions(String query, Pageable pageable, Long customerId) { @@ -73,6 +79,7 @@ public class AdoptionService { adoption.setAdoptionDate(request.getAdoptionDate()); adoption.setAdoptionStatus(request.getAdoptionStatus()); + adoption = adoptionRepository.save(adoption); return mapToResponse(adoption); } @@ -92,7 +99,12 @@ public class AdoptionService { adoption.setCustomer(customer); adoption.setAdoptionDate(request.getAdoptionDate()); adoption.setAdoptionStatus(request.getAdoptionStatus()); - + if (request.getEmployeeId() != null) { + Employee employee = employeeRepository.findById(request.getEmployeeId()) + .orElseThrow(() -> new ResourceNotFoundException( + "Employee not found with id: " + request.getEmployeeId())); + adoption.setEmployee(employee); + } adoption = adoptionRepository.save(adoption); return mapToResponse(adoption); } @@ -111,17 +123,27 @@ public class AdoptionService { } private AdoptionResponse mapToResponse(Adoption adoption) { - return new AdoptionResponse( - adoption.getAdoptionId(), - adoption.getPet().getPetId(), - adoption.getPet().getPetName(), - adoption.getCustomer().getCustomerId(), - adoption.getCustomer().getFirstName() + " " + adoption.getCustomer().getLastName(), - adoption.getAdoptionDate(), - adoption.getAdoptionStatus(), - adoption.getPet().getPetPrice(), - adoption.getCreatedAt(), - adoption.getUpdatedAt() + AdoptionResponse response = new AdoptionResponse( + adoption.getAdoptionId(), + adoption.getPet().getPetId(), + adoption.getPet().getPetName(), + adoption.getCustomer().getCustomerId(), + adoption.getCustomer().getFirstName() + " " + adoption.getCustomer().getLastName(), + adoption.getAdoptionDate(), + adoption.getAdoptionStatus(), + adoption.getPet().getPetPrice(), + adoption.getCreatedAt(), + adoption.getUpdatedAt() ); + // Add employee name + if (adoption.getEmployee() != null) { + response.setEmployeeId(adoption.getEmployee().getEmployeeId()); + response.setEmployeeName( + adoption.getEmployee().getFirstName() + " " + + adoption.getEmployee().getLastName()); + } else { + response.setEmployeeName("Unassigned"); + } + return response; } } diff --git a/backend/src/main/java/com/petshop/backend/service/AppointmentService.java b/backend/src/main/java/com/petshop/backend/service/AppointmentService.java index ef5f9cdb..34fc087d 100644 --- a/backend/src/main/java/com/petshop/backend/service/AppointmentService.java +++ b/backend/src/main/java/com/petshop/backend/service/AppointmentService.java @@ -98,6 +98,16 @@ public class AppointmentService { Customer customer = customerRepository.findById(request.getCustomerId()) .orElseThrow(() -> new ResourceNotFoundException("Customer not found with id: " + request.getCustomerId())); + Employee employee; + if (request.getEmployeeId() != null) { + employee = employeeRepository.findById(request.getEmployeeId()) + .orElseThrow(() -> new ResourceNotFoundException( + "Employee not found with id: " + request.getEmployeeId())); + } else { + employee = AuthenticationHelper.getAuthenticatedEmployee( + userRepository, employeeRepository); + } + StoreLocation store = storeRepository.findById(request.getStoreId()) .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId())); @@ -113,6 +123,7 @@ public class AppointmentService { appointment.setCustomer(customer); appointment.setStore(store); appointment.setService(service); + appointment.setEmployee(employee); appointment.setAppointmentDate(request.getAppointmentDate()); appointment.setAppointmentTime(request.getAppointmentTime()); appointment.setAppointmentStatus(request.getAppointmentStatus()); @@ -246,7 +257,13 @@ public class AppointmentService { petNames, petIds, appointment.getCreatedAt(), - appointment.getUpdatedAt() + appointment.getUpdatedAt(), + appointment.getEmployee() != null ? appointment.getEmployee().getEmployeeId() : null, + appointment.getEmployee() != null ? + appointment.getEmployee().getFirstName() + " " + appointment.getEmployee().getLastName() + : "Unassigned" + + ); }