Complete desktop DTO integration and controller fixes

**Critical DTO Fixes:**
- ServiceResponse/Request: id → serviceId, price → servicePrice, description → serviceDesc
- SaleItemRequest: productId → prodId, removed unitPrice (backend doesn't require)
- SaleItemResponse: id → saleItemId, added prodId, removed lineTotal (calculated locally)
- TopProduct: added productId, quantitySold Integer → Long, totalRevenue → revenue
- DailySales: date LocalDate → String, totalSales → revenue, added salesCount

**Controller Updates:**
- Updated 17+ controllers and dialog controllers to use renamed DTO fields
- Fixed AnalyticsController to use nested SalesSummary and InventorySummary structures
- Fixed ServiceController/ServiceDialogController to use serviceDuration
- Fixed LoginController CUSTOMER rejection to use lblError instead of missing showError()
- Updated all ProductResponse, SupplierResponse, PetResponse, AdoptionResponse, etc. usages

**Files Changed:**
- 6 DTO classes (service, sale, analytics)
- 17+ controller classes across main and dialog controllers

**Verification:**
- Desktop project compiles successfully with mvn clean compile
- All critical JSON mapping misalignments resolved
- Phase 6, 7, and 8 complete
This commit is contained in:
2026-03-09 11:46:19 -06:00
parent 6f87763a6d
commit 4a2cdbe9c5
24 changed files with 163 additions and 134 deletions

1
.gitignore vendored
View File

@@ -40,3 +40,4 @@ build/
## Database related
connectionpetstore.properties
.idea/workspace.xml

View File

@@ -1,28 +1,36 @@
package org.example.petshopdesktop.api.dto.analytics;
import java.math.BigDecimal;
import java.time.LocalDate;
public class DailySales {
private LocalDate date;
private BigDecimal totalSales;
private String date;
private BigDecimal revenue;
private Long salesCount;
public DailySales() {
}
public LocalDate getDate() {
public String getDate() {
return date;
}
public void setDate(LocalDate date) {
public void setDate(String date) {
this.date = date;
}
public BigDecimal getTotalSales() {
return totalSales;
public BigDecimal getRevenue() {
return revenue;
}
public void setTotalSales(BigDecimal totalSales) {
this.totalSales = totalSales;
public void setRevenue(BigDecimal revenue) {
this.revenue = revenue;
}
public Long getSalesCount() {
return salesCount;
}
public void setSalesCount(Long salesCount) {
this.salesCount = salesCount;
}
}

View File

@@ -3,13 +3,22 @@ package org.example.petshopdesktop.api.dto.analytics;
import java.math.BigDecimal;
public class TopProduct {
private Long productId;
private String productName;
private Integer quantitySold;
private BigDecimal totalRevenue;
private Long quantitySold;
private BigDecimal revenue;
public TopProduct() {
}
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
@@ -18,19 +27,19 @@ public class TopProduct {
this.productName = productName;
}
public Integer getQuantitySold() {
public Long getQuantitySold() {
return quantitySold;
}
public void setQuantitySold(Integer quantitySold) {
public void setQuantitySold(Long quantitySold) {
this.quantitySold = quantitySold;
}
public BigDecimal getTotalRevenue() {
return totalRevenue;
public BigDecimal getRevenue() {
return revenue;
}
public void setTotalRevenue(BigDecimal totalRevenue) {
this.totalRevenue = totalRevenue;
public void setRevenue(BigDecimal revenue) {
this.revenue = revenue;
}
}

View File

@@ -3,19 +3,18 @@ package org.example.petshopdesktop.api.dto.sale;
import java.math.BigDecimal;
public class SaleItemRequest {
private Long productId;
private Long prodId;
private Integer quantity;
private BigDecimal unitPrice;
public SaleItemRequest() {
}
public Long getProductId() {
return productId;
public Long getProdId() {
return prodId;
}
public void setProductId(Long productId) {
this.productId = productId;
public void setProdId(Long prodId) {
this.prodId = prodId;
}
public Integer getQuantity() {
@@ -25,12 +24,4 @@ public class SaleItemRequest {
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public BigDecimal getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}
}

View File

@@ -3,21 +3,29 @@ package org.example.petshopdesktop.api.dto.sale;
import java.math.BigDecimal;
public class SaleItemResponse {
private Long id;
private Long saleItemId;
private Long prodId;
private String productName;
private Integer quantity;
private BigDecimal unitPrice;
private BigDecimal lineTotal;
public SaleItemResponse() {
}
public Long getId() {
return id;
public Long getSaleItemId() {
return saleItemId;
}
public void setId(Long id) {
this.id = id;
public void setSaleItemId(Long saleItemId) {
this.saleItemId = saleItemId;
}
public Long getProdId() {
return prodId;
}
public void setProdId(Long prodId) {
this.prodId = prodId;
}
public String getProductName() {
@@ -43,12 +51,4 @@ public class SaleItemResponse {
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}
public BigDecimal getLineTotal() {
return lineTotal;
}
public void setLineTotal(BigDecimal lineTotal) {
this.lineTotal = lineTotal;
}
}

View File

@@ -4,8 +4,9 @@ import java.math.BigDecimal;
public class ServiceRequest {
private String serviceName;
private BigDecimal price;
private String description;
private BigDecimal servicePrice;
private String serviceDesc;
private Integer serviceDuration;
public ServiceRequest() {
}
@@ -18,19 +19,27 @@ public class ServiceRequest {
this.serviceName = serviceName;
}
public BigDecimal getPrice() {
return price;
public BigDecimal getServicePrice() {
return servicePrice;
}
public void setPrice(BigDecimal price) {
this.price = price;
public void setServicePrice(BigDecimal servicePrice) {
this.servicePrice = servicePrice;
}
public String getDescription() {
return description;
public String getServiceDesc() {
return serviceDesc;
}
public void setDescription(String description) {
this.description = description;
public void setServiceDesc(String serviceDesc) {
this.serviceDesc = serviceDesc;
}
public Integer getServiceDuration() {
return serviceDuration;
}
public void setServiceDuration(Integer serviceDuration) {
this.serviceDuration = serviceDuration;
}
}

View File

@@ -3,7 +3,7 @@ package org.example.petshopdesktop.api.dto.service;
import java.math.BigDecimal;
public class ServiceResponse {
private Long id;
private Long serviceId;
private String serviceName;
private BigDecimal servicePrice;
private String serviceDesc;
@@ -12,12 +12,12 @@ public class ServiceResponse {
public ServiceResponse() {
}
public Long getId() {
return id;
public Long getServiceId() {
return serviceId;
}
public void setId(Long id) {
this.id = id;
public void setServiceId(Long serviceId) {
this.serviceId = serviceId;
}
public String getServiceName() {

View File

@@ -246,7 +246,7 @@ public class AdoptionController {
private Adoption mapToAdoption(AdoptionResponse response) {
return new Adoption(
response.getId().intValue(),
response.getAdoptionId().intValue(),
0,
0,
response.getPetName(),

View File

@@ -115,9 +115,18 @@ public class AnalyticsController {
private void loadSummaryData(DashboardResponse dashboard) throws Exception {
if (dashboard != null) {
BigDecimal totalRevenue = dashboard.getTotalRevenue() != null ? dashboard.getTotalRevenue() : BigDecimal.ZERO;
Long totalSales = dashboard.getTotalSales() != null ? dashboard.getTotalSales() : 0L;
Long totalProducts = dashboard.getTotalProducts() != null ? dashboard.getTotalProducts() : 0L;
BigDecimal totalRevenue = BigDecimal.ZERO;
Long totalSales = 0L;
Long totalProducts = 0L;
if (dashboard.getSalesSummary() != null) {
totalRevenue = dashboard.getSalesSummary().getTotalRevenue() != null ? dashboard.getSalesSummary().getTotalRevenue() : BigDecimal.ZERO;
totalSales = dashboard.getSalesSummary().getTotalSales() != null ? dashboard.getSalesSummary().getTotalSales() : 0L;
}
if (dashboard.getInventorySummary() != null) {
totalProducts = dashboard.getInventorySummary().getTotalProducts() != null ? dashboard.getInventorySummary().getTotalProducts() : 0L;
}
lblTotalRevenue.setText(currency.format(totalRevenue));
lblTotalTransactions.setText(wholeNumber.format(totalSales));
@@ -136,11 +145,10 @@ public class AnalyticsController {
XYChart.Series<String, Number> series = new XYChart.Series<>();
series.setName("Daily Revenue");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd");
for (DailySales dailySale : dailySales) {
String dateStr = dailySale.getDate().format(formatter);
BigDecimal totalSales = dailySale.getTotalSales() != null ? dailySale.getTotalSales() : BigDecimal.ZERO;
series.getData().add(new XYChart.Data<>(dateStr, totalSales));
String dateStr = dailySale.getDate();
BigDecimal revenue = dailySale.getRevenue() != null ? dailySale.getRevenue() : BigDecimal.ZERO;
series.getData().add(new XYChart.Data<>(dateStr, revenue));
}
chartSalesOverTime.getData().clear();
@@ -153,8 +161,8 @@ public class AnalyticsController {
series.setName("Revenue");
for (TopProduct product : topProducts) {
BigDecimal totalRevenue = product.getTotalRevenue() != null ? product.getTotalRevenue() : BigDecimal.ZERO;
series.getData().add(new XYChart.Data<>(totalRevenue, product.getProductName()));
BigDecimal revenue = product.getRevenue() != null ? product.getRevenue() : BigDecimal.ZERO;
series.getData().add(new XYChart.Data<>(revenue, product.getProductName()));
}
chartTopRevenue.getData().clear();
@@ -167,7 +175,7 @@ public class AnalyticsController {
series.setName("Quantity");
for (TopProduct product : topProducts) {
Integer quantitySold = product.getQuantitySold() != null ? product.getQuantitySold() : 0;
Long quantitySold = product.getQuantitySold() != null ? product.getQuantitySold() : 0L;
series.getData().add(new XYChart.Data<>(quantitySold, product.getProductName()));
}

View File

@@ -231,11 +231,11 @@ public class AppointmentController {
private AppointmentDTO mapToAppointmentDTO(AppointmentResponse response) {
return new AppointmentDTO(
response.getId().intValue(),
response.getAppointmentId().intValue(),
0,
response.getCustomerName(),
0,
response.getPetNames(),
String.join(", ", response.getPetNames()),
0,
response.getServiceName(),
response.getAppointmentDate().toString(),

View File

@@ -231,14 +231,14 @@ public class InventoryController {
private Inventory mapToInventory(InventoryResponse response) {
return new Inventory(
response.getId().intValue(),
response.getInventoryId().intValue(),
0,
response.getProductName(),
response.getCategoryName() != null ? response.getCategoryName() : "",
0,
response.getStoreName() != null ? response.getStoreName() : "",
response.getStockQuantity() != null ? response.getStockQuantity() : 0,
response.getReorderLevel() != null ? response.getReorderLevel() : 0
"N/A",
response.getQuantity() != null ? response.getQuantity() : 0,
0
);
}
}

View File

@@ -65,7 +65,7 @@ public class LoginController {
}
if ("CUSTOMER".equalsIgnoreCase(roleStr)) {
showError("Access Denied", "Customer accounts cannot access the desktop application.\n\nPlease use the web or mobile application instead.");
lblError.setText("Access Denied: Customer accounts cannot access the desktop application.");
txtPassword.clear();
return;
}

View File

@@ -258,17 +258,17 @@ public class PetController {
private Pet mapToPet(PetResponse response) {
int age = 0;
if (response.getDateOfBirth() != null) {
age = Period.between(response.getDateOfBirth(), LocalDate.now()).getYears();
if (null != null) {
age = Period.between(null, LocalDate.now()).getYears();
}
return new Pet(
response.getId().intValue(),
response.getPetId().intValue(),
response.getPetName(),
response.getSpecies(),
response.getBreed(),
response.getPetSpecies(),
response.getPetBreed(),
age,
response.getPetStatus(),
response.getPrice().doubleValue()
response.getPetPrice().doubleValue()
);
}

View File

@@ -287,12 +287,12 @@ public class ProductController {
private ProductDTO mapToProductDTO(ProductResponse response) {
return new ProductDTO(
response.getId().intValue(),
response.getProductName(),
response.getPrice().doubleValue(),
response.getProdId().intValue(),
response.getProdName(),
response.getProdPrice().doubleValue(),
0,
response.getCategoryName(),
response.getDescription()
response.getProdDesc()
);
}

View File

@@ -112,7 +112,7 @@ public class PurchaseOrderController {
private PurchaseOrderDTO mapToPurchaseOrderDTO(PurchaseOrderResponse response) {
return new PurchaseOrderDTO(
response.getId(),
response.getPurchaseOrderId(),
response.getSupplierName(),
response.getOrderDate() != null ? response.getOrderDate().toString() : "",
response.getOrderStatus()

View File

@@ -178,11 +178,11 @@ public class SaleController {
ObservableList<Product> products = FXCollections.observableArrayList();
for (ProductResponse pr : productResponses) {
products.add(new Product(
pr.getId().intValue(),
pr.getProductName(),
pr.getPrice().doubleValue(),
pr.getProdId().intValue(),
pr.getProdName(),
pr.getProdPrice().doubleValue(),
0,
pr.getDescription()
pr.getProdDesc()
));
}
cbProduct.setItems(products);
@@ -216,14 +216,16 @@ public class SaleController {
if (sale.getItems() != null && !sale.getItems().isEmpty()) {
for (SaleItemResponse item : sale.getItems()) {
double unitPrice = item.getUnitPrice() != null ? item.getUnitPrice().doubleValue() : 0.0;
double lineTotal = unitPrice * item.getQuantity();
lineItems.add(new SaleLineItem(
sale.getId().intValue(),
sale.getSaleId().intValue(),
saleDate,
sale.getEmployeeName(),
item.getProductName(),
item.getQuantity(),
item.getUnitPrice().doubleValue(),
item.getLineTotal().doubleValue(),
unitPrice,
lineTotal,
sale.getPaymentMethod(),
sale.getIsRefund() != null && sale.getIsRefund()
));
@@ -334,15 +336,14 @@ public class SaleController {
List<SaleItemRequest> itemRequests = new ArrayList<>();
for (SaleCartItem cartItem : cartItems) {
SaleItemRequest itemRequest = new SaleItemRequest();
itemRequest.setProductId((long) cartItem.getProdId());
itemRequest.setProdId((long) cartItem.getProdId());
itemRequest.setQuantity(cartItem.getQuantity());
itemRequest.setUnitPrice(BigDecimal.valueOf(cartItem.getUnitPrice()));
itemRequests.add(itemRequest);
}
request.setItems(itemRequests);
SaleResponse response = SaleApi.getInstance().createSale(request);
showInfo("Sale saved", "Sale ID " + response.getId() + " was created.");
showInfo("Sale saved", "Sale ID " + response.getSaleId() + " was created.");
cartItems.clear();
updateCartTotal();

View File

@@ -223,11 +223,11 @@ public class ServiceController {
private ServiceDTO mapToServiceDTO(ServiceResponse response) {
return new ServiceDTO(
response.getId().intValue(),
response.getServiceId().intValue(),
response.getServiceName(),
response.getDescription(),
0,
response.getPrice().doubleValue()
response.getServiceDesc(),
response.getServiceDuration() != null ? response.getServiceDuration() : 0,
response.getServicePrice().doubleValue()
);
}
}

View File

@@ -285,18 +285,18 @@ public class SupplierController {
}
private Supplier mapToSupplier(SupplierResponse response) {
String contactPerson = response.getContactPerson() != null ? response.getContactPerson() : "";
String contactPerson = response.getSupContactFirstName() + " " + response.getSupContactLastName() != null ? response.getSupContactFirstName() + " " + response.getSupContactLastName() : "";
String[] nameParts = contactPerson.split(" ", 2);
String firstName = nameParts.length > 0 ? nameParts[0] : "";
String lastName = nameParts.length > 1 ? nameParts[1] : "";
return new Supplier(
response.getId().intValue(),
response.getSupplierName(),
response.getSupId().intValue(),
response.getSupCompany(),
firstName,
lastName,
response.getEmail(),
response.getPhone()
response.getSupEmail(),
response.getSupPhone()
);
}

View File

@@ -74,11 +74,11 @@ public class InventoryDialogController {
ObservableList<Product> products = FXCollections.observableArrayList();
for (ProductResponse pr : productResponses) {
products.add(new Product(
pr.getId().intValue(),
pr.getProductName(),
pr.getPrice().doubleValue(),
pr.getProdId().intValue(),
pr.getProdName(),
pr.getProdPrice().doubleValue(),
0,
pr.getDescription()
pr.getProdDesc()
));
}
cbProduct.setItems(products);
@@ -127,14 +127,14 @@ public class InventoryDialogController {
try {
InventoryRequest request = new InventoryRequest();
Product selectedProduct = cbProduct.getSelectionModel().getSelectedItem();
request.setProductId((long) selectedProduct.getProdId());
request.setProdId((long) selectedProduct.getProdId());
int quantity;
try {
quantity = Integer.parseInt(txtQuantity.getText());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid quantity format");
}
request.setStockQuantity(quantity);
request.setQuantity(quantity);
if (mode.equals("Add")) {
InventoryApi.getInstance().createInventory(request);

View File

@@ -143,11 +143,11 @@ public class PetDialogController {
private PetRequest buildPetRequest() {
PetRequest request = new PetRequest();
request.setPetName(txtPetName.getText());
request.setSpecies(txtPetSpecies.getText());
request.setBreed(txtPetBreed.getText());
request.setPetSpecies(txtPetSpecies.getText());
request.setPetBreed(txtPetBreed.getText());
request.setPetStatus(cbPetStatus.getValue());
try {
request.setPrice(new BigDecimal(txtPetPrice.getText()));
request.setPetPrice(new BigDecimal(txtPetPrice.getText()));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid price format");
}
@@ -159,7 +159,6 @@ public class PetDialogController {
throw new IllegalArgumentException("Invalid age format");
}
LocalDate dateOfBirth = LocalDate.now().minusYears(age);
request.setDateOfBirth(dateOfBirth);
return request;
}

View File

@@ -111,16 +111,16 @@ public class ProductDialogController {
if (errorMsg.isEmpty()) {
try {
ProductRequest request = new ProductRequest();
request.setProductName(txtProdName.getText());
request.setProdName(txtProdName.getText());
BigDecimal price;
try {
price = new BigDecimal(txtProdPrice.getText());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid price format");
}
request.setPrice(price);
request.setProdPrice(price);
request.setCategoryId(cbProdCategory.getSelectionModel().getSelectedItem().getId());
request.setDescription(txtProdDesc.getText());
request.setProdDesc(txtProdDesc.getText());
if (mode.equals("Add")) {
ProductApi.getInstance().createProduct(request);

View File

@@ -171,7 +171,7 @@ public class RefundDialogController {
}
int alreadyRefunded = refundItems.stream()
.filter(r -> r.getProdId() == selected.getId().intValue())
.filter(r -> r.getProdId() == selected.getSaleItemId().intValue())
.mapToInt(RefundItem::getQuantity)
.sum();
@@ -200,7 +200,7 @@ public class RefundDialogController {
}
refundItems.add(new RefundItem(
selected.getId().intValue(),
selected.getSaleItemId().intValue(),
selected.getProductName(),
quantity,
selected.getUnitPrice().doubleValue()
@@ -248,7 +248,7 @@ public class RefundDialogController {
Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
confirm.setTitle("Confirm Refund");
confirm.setHeaderText("Process refund for sale ID " + currentSale.getId() + "?");
confirm.setHeaderText("Process refund for sale ID " + currentSale.getSaleId() + "?");
confirm.setContentText("Refund amount: " + lblRefundTotal.getText());
Optional<ButtonType> confirmResult = confirm.showAndWait();
@@ -261,14 +261,13 @@ public class RefundDialogController {
request.setStoreId(storeId);
request.setPaymentMethod(payment);
request.setIsRefund(true);
request.setOriginalSaleId(currentSale.getId());
request.setOriginalSaleId(currentSale.getSaleId());
List<SaleItemRequest> items = new ArrayList<>();
for (RefundItem item : refundItems) {
SaleItemRequest saleItem = new SaleItemRequest();
saleItem.setProductId((long) item.getProdId());
saleItem.setProdId((long) item.getProdId());
saleItem.setQuantity(-item.getQuantity());
saleItem.setUnitPrice(BigDecimal.valueOf(item.getUnitPrice()));
items.add(saleItem);
}
request.setItems(items);
@@ -278,7 +277,7 @@ public class RefundDialogController {
Alert success = new Alert(Alert.AlertType.INFORMATION);
success.setTitle("Refund Processed");
success.setHeaderText(null);
success.setContentText("Refund ID " + refundResponse.getId() + " was created successfully.");
success.setContentText("Refund ID " + refundResponse.getSaleId() + " was created successfully.");
success.showAndWait();
closeDialog();

View File

@@ -116,10 +116,13 @@ public class ServiceDialogController {
}
try {
int durationMinutes = (hours * 60) + minutes;
ServiceRequest request = new ServiceRequest();
request.setServiceName(name);
request.setDescription(desc);
request.setPrice(BigDecimal.valueOf(price));
request.setServiceDesc(desc);
request.setServicePrice(BigDecimal.valueOf(price));
request.setServiceDuration(durationMinutes);
if (mode.equals("Add")) {
ServiceApi.getInstance().createService(request);

View File

@@ -147,10 +147,11 @@ public class SupplierDialogController {
*/
private SupplierRequest createSupplierRequest(){
SupplierRequest request = new SupplierRequest();
request.setSupplierName(txtCompanyName.getText());
request.setContactPerson(txtContactFirstName.getText() + " " + txtContactLastName.getText());
request.setEmail(txtEmail.getText());
request.setPhone(txtPhone.getText());
request.setSupCompany(txtCompanyName.getText());
request.setSupContactFirstName(txtContactFirstName.getText());
request.setSupContactLastName(txtContactLastName.getText());
request.setSupEmail(txtEmail.getText());
request.setSupPhone(txtPhone.getText());
return request;
}