diff --git a/backend/src/main/java/com/petshop/backend/dto/adoption/AdoptionRequest.java b/backend/src/main/java/com/petshop/backend/dto/adoption/AdoptionRequest.java index d3700bfc..7fb9ceac 100644 --- a/backend/src/main/java/com/petshop/backend/dto/adoption/AdoptionRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/adoption/AdoptionRequest.java @@ -22,6 +22,8 @@ public class AdoptionRequest { private Long sourceStoreId; + private String paymentMethod; + public Long getPetId() { return petId; } @@ -70,6 +72,14 @@ public class AdoptionRequest { this.sourceStoreId = sourceStoreId; } + public String getPaymentMethod() { + return paymentMethod; + } + + public void setPaymentMethod(String paymentMethod) { + this.paymentMethod = paymentMethod; + } + @Override public boolean equals(Object o) { if (this == o) return true; 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 9855a3e6..d7dc0590 100644 --- a/backend/src/main/java/com/petshop/backend/service/AdoptionService.java +++ b/backend/src/main/java/com/petshop/backend/service/AdoptionService.java @@ -5,11 +5,13 @@ 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.Pet; +import com.petshop.backend.entity.Sale; import com.petshop.backend.entity.StoreLocation; import com.petshop.backend.entity.User; import com.petshop.backend.exception.ResourceNotFoundException; import com.petshop.backend.repository.AdoptionRepository; import com.petshop.backend.repository.PetRepository; +import com.petshop.backend.repository.SaleRepository; import com.petshop.backend.repository.StoreRepository; import com.petshop.backend.repository.UserRepository; import org.springframework.data.domain.Page; @@ -17,7 +19,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.time.LocalDate; +import java.time.LocalDateTime; @Service public class AdoptionService { @@ -32,12 +36,14 @@ public class AdoptionService { private final PetRepository petRepository; private final UserRepository userRepository; private final StoreRepository storeRepository; + private final SaleRepository saleRepository; - public AdoptionService(AdoptionRepository adoptionRepository, PetRepository petRepository, UserRepository userRepository, StoreRepository storeRepository) { + public AdoptionService(AdoptionRepository adoptionRepository, PetRepository petRepository, UserRepository userRepository, StoreRepository storeRepository, SaleRepository saleRepository) { this.adoptionRepository = adoptionRepository; this.petRepository = petRepository; this.userRepository = userRepository; this.storeRepository = storeRepository; + this.saleRepository = saleRepository; } public Page getAllAdoptions(String query, Long customerId, String status, Long storeId, LocalDate date, Pageable pageable) { @@ -95,6 +101,9 @@ public class AdoptionService { adoption = adoptionRepository.save(adoption); syncPetStatus(pet, adoptionStatus, adoption.getAdoptionId(), customer); + if (ADOPTION_STATUS_COMPLETED.equalsIgnoreCase(adoptionStatus)) { + createSaleForAdoption(adoption, request.getPaymentMethod()); + } return mapToResponse(adoption); } @@ -113,6 +122,7 @@ public class AdoptionService { ? storeRepository.findById(request.getSourceStoreId()) .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getSourceStoreId())) : null; + boolean wasCompleted = ADOPTION_STATUS_COMPLETED.equalsIgnoreCase(adoption.getAdoptionStatus()); String adoptionStatus = normalizeAdoptionStatus(request.getAdoptionStatus()); Long currentPetId = adoption.getPet() != null ? adoption.getPet().getPetId() : null; validatePetAvailability(pet, adoption.getAdoptionId(), currentPetId); @@ -129,6 +139,9 @@ public class AdoptionService { adoption = adoptionRepository.save(adoption); syncPetStatus(pet, adoptionStatus, adoption.getAdoptionId(), customer); + if (!wasCompleted && ADOPTION_STATUS_COMPLETED.equalsIgnoreCase(adoptionStatus)) { + createSaleForAdoption(adoption, request.getPaymentMethod()); + } return mapToResponse(adoption); } @@ -222,6 +235,27 @@ public class AdoptionService { } } + private void createSaleForAdoption(Adoption adoption, String paymentMethod) { + if (adoption.getEmployee() == null || adoption.getSourceStore() == null) { + return; + } + BigDecimal amount = adoption.getPet().getPetPrice(); + if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { + amount = BigDecimal.ZERO; + } + Sale sale = new Sale(); + sale.setSaleDate(LocalDateTime.now()); + sale.setEmployee(adoption.getEmployee()); + sale.setStore(adoption.getSourceStore()); + sale.setCustomer(adoption.getCustomer()); + sale.setTotalAmount(amount); + sale.setSubtotalAmount(amount); + sale.setPaymentMethod(paymentMethod != null && !paymentMethod.isBlank() ? paymentMethod : "Cash"); + sale.setIsRefund(false); + sale.setChannel("ADOPTION"); + saleRepository.save(sale); + } + private void syncPetStatus(Pet pet, String adoptionStatus, Long adoptionId, User customer) { boolean completedElsewhere = adoptionId != null && adoptionRepository.existsByPet_IdAndAdoptionStatusIgnoreCaseAndAdoptionIdNot(pet.getPetId(), ADOPTION_STATUS_COMPLETED, adoptionId); diff --git a/desktop/src/main/java/org/example/petshopdesktop/api/dto/adoption/AdoptionRequest.java b/desktop/src/main/java/org/example/petshopdesktop/api/dto/adoption/AdoptionRequest.java index af596ade..75ece4d9 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/api/dto/adoption/AdoptionRequest.java +++ b/desktop/src/main/java/org/example/petshopdesktop/api/dto/adoption/AdoptionRequest.java @@ -9,6 +9,7 @@ public class AdoptionRequest { private Long sourceStoreId; private LocalDate adoptionDate; private String adoptionStatus; + private String paymentMethod; public AdoptionRequest() { } @@ -60,4 +61,12 @@ public class AdoptionRequest { public void setAdoptionStatus(String adoptionStatus) { this.adoptionStatus = adoptionStatus; } + + public String getPaymentMethod() { + return paymentMethod; + } + + public void setPaymentMethod(String paymentMethod) { + this.paymentMethod = paymentMethod; + } } diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java index 534d9feb..b9056214 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java @@ -8,6 +8,7 @@ import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.Button; +import javafx.scene.control.ChoiceDialog; import javafx.scene.control.ComboBox; import javafx.scene.control.DatePicker; import javafx.scene.control.Label; @@ -57,6 +58,7 @@ public class AdoptionDialogController { private String mode = null; private Adoption selectedAdoption = null; + private String selectedPaymentMethod = null; private ObservableList statusList = FXCollections.observableArrayList( "Pending", "Completed", "Cancelled" @@ -66,6 +68,23 @@ public class AdoptionDialogController { void initialize() { cbAdoptionStatus.setItems(statusList); + cbAdoptionStatus.valueProperty().addListener((obs, oldVal, newVal) -> { + if ("Completed".equals(newVal) && !"Completed".equals(oldVal)) { + ChoiceDialog dialog = new ChoiceDialog<>("Cash", "Cash", "Credit Card", "Debit Card", "E-Transfer"); + dialog.setTitle("Payment Method"); + dialog.setHeaderText("Confirm payment received"); + dialog.setContentText("Select payment method:"); + dialog.showAndWait().ifPresentOrElse( + method -> selectedPaymentMethod = method, + () -> { + selectedPaymentMethod = null; + cbAdoptionStatus.setValue(oldVal); + } + ); + } else if (!"Completed".equals(newVal)) { + selectedPaymentMethod = null; + } + }); cbEmployee.setPromptText("Select an employee"); new Thread(() -> { @@ -203,6 +222,7 @@ public class AdoptionDialogController { request.setSourceStoreId(storeId); request.setAdoptionDate(dpAdoptionDate.getValue()); request.setAdoptionStatus(cbAdoptionStatus.getValue()); + request.setPaymentMethod(selectedPaymentMethod); if (mode.equals("Add")) { AdoptionApi.getInstance().createAdoption(request);