Fix desktop ProductSupplier to use composite keys

- Remove id field from ProductSupplierResponse
- Rename supplierPrice to cost in ProductSupplierResponse and ProductSupplierRequest
- Update ProductSupplierApi to use composite keys (productId, supplierId) for update and delete
- Update ProductSupplierController delete logic to iterate and delete with composite keys
- Update ProductSupplierController mapping to use getCost() instead of getSupplierPrice()
- Update ProductSupplierDialogController to pass both productId and supplierId to update
- Update ProductSupplierDialogController to use setCost() instead of setSupplierPrice()
- Remove unused selectedId field from ProductSupplierDialogController
This commit is contained in:
2026-03-08 22:01:10 -06:00
parent 59de8ae1aa
commit d4e532a798
34 changed files with 206 additions and 39 deletions

67
log.txt
View File

@@ -49,3 +49,70 @@ The last packet sent successfully to the server was 0 milliseconds ago. The driv
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Authentication attempt for username: staff
[2026-03-07 17:50:34] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Authentication attempt for username: staff
[2026-03-07 17:55:02] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Authentication attempt for username: staff
[2026-03-07 17:55:16] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Authentication attempt for username: staff
[2026-03-07 18:11:05] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: ConnectException | Message: null | Context: Authentication attempt for username: staff
[2026-03-07 18:11:42] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: RuntimeException | Message: Authentication failed. Please log in again. | Context: Authentication attempt for username: staff
[2026-03-07 18:11:48] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:11:52] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.product.ProductResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Loading products
[2026-03-07 18:11:52] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.sale.SaleResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Loading sales
[2026-03-07 18:11:53] [ERROR] EXCEPTION | Location: AppointmentController.loadAppointments | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.appointment.AppointmentResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Loading appointments for table display
[2026-03-07 18:11:53] [ERROR] EXCEPTION | Location: ServiceController.displayServices | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.service.ServiceResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching service data for table display
[2026-03-07 18:11:54] [ERROR] EXCEPTION | Location: ServiceController.displayServices | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.service.ServiceResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching service data for table display
[2026-03-07 18:11:56] [ERROR] EXCEPTION | Location: PetController.displayPets | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.pet.PetResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching pet data for table display
[2026-03-07 18:11:56] [ERROR] EXCEPTION | Location: PetController.displayPets | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.pet.PetResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching pet data for table display
[2026-03-07 18:11:56] [ERROR] EXCEPTION | Location: AdoptionController.displayAdoptions | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.adoption.AdoptionResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching adoption data for table display
[2026-03-07 18:11:57] [ERROR] EXCEPTION | Location: ProductController.displayProduct | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.util.ArrayList<org.example.petshopdesktop.api.dto.product.ProductResponse>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] | Context: Fetching product data for table display
[2026-03-07 18:11:58] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:47:48] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:48:01] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:48:05] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:48:05] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:51:14] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:51:14] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:51:28] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-07 18:51:30] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-08 10:03:43] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Loading products
[2026-03-08 10:03:43] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:03:44] [ERROR] EXCEPTION | Location: AppointmentController.loadAppointments | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 219] (through reference chain: org.example.petshopdesktop.api.dto.common.PageResponse["content"]->java.util.ArrayList[0]->org.example.petshopdesktop.api.dto.appointment.AppointmentResponse["petNames"]) | Context: Loading appointments for table display
[2026-03-08 10:03:44] [ERROR] EXCEPTION | Location: ServiceController.displayServices | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.service.ServiceResponse.getId()" is null | Context: Fetching service data for table display
[2026-03-08 10:03:45] [ERROR] EXCEPTION | Location: ServiceController.displayServices | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.service.ServiceResponse.getId()" is null | Context: Fetching service data for table display
[2026-03-08 10:03:46] [ERROR] EXCEPTION | Location: PetController.displayPets | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.pet.PetResponse.getId()" is null | Context: Fetching pet data for table display
[2026-03-08 10:03:46] [ERROR] EXCEPTION | Location: AdoptionController.displayAdoptions | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.adoption.AdoptionResponse.getId()" is null | Context: Fetching adoption data for table display
[2026-03-08 10:03:47] [ERROR] EXCEPTION | Location: AdoptionController.displayAdoptions | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.adoption.AdoptionResponse.getId()" is null | Context: Fetching adoption data for table display
[2026-03-08 10:03:47] [ERROR] EXCEPTION | Location: ProductController.displayProduct | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Fetching product data for table display
[2026-03-08 10:03:48] [ERROR] EXCEPTION | Location: InventoryController.displayInventory | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.inventory.InventoryResponse.getId()" is null | Context: Fetching inventory data for table display
[2026-03-08 10:03:48] [ERROR] EXCEPTION | Location: ProductSupplierController.displayProductSupplier | Type: NullPointerException | Message: Cannot invoke "java.math.BigDecimal.doubleValue()" because the return value of "org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierResponse.getSupplierPrice()" is null | Context: Fetching product-supplier data for table display
[2026-03-08 10:03:49] [ERROR] EXCEPTION | Location: SupplierController.displaySupplier | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.supplier.SupplierResponse.getId()" is null | Context: Fetching supplier data for table display
[2026-03-08 10:03:50] [ERROR] EXCEPTION | Location: PurchaseOrderController.loadPurchaseOrders | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.longValue()" because the return value of "org.example.petshopdesktop.api.dto.purchaseorder.PurchaseOrderResponse.getId()" is null | Context: Loading purchase orders for table display
[2026-03-08 10:04:02] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Loading products
[2026-03-08 10:04:02] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:04:03] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:05:41] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-08 10:05:44] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-08 10:05:46] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Loading products
[2026-03-08 10:05:46] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:05:47] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Loading products
[2026-03-08 10:05:47] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:05:47] [ERROR] EXCEPTION | Location: AppointmentController.loadAppointments | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 219] (through reference chain: org.example.petshopdesktop.api.dto.common.PageResponse["content"]->java.util.ArrayList[0]->org.example.petshopdesktop.api.dto.appointment.AppointmentResponse["petNames"]) | Context: Loading appointments for table display
[2026-03-08 10:05:48] [ERROR] EXCEPTION | Location: AppointmentController.loadAppointments | Type: MismatchedInputException | Message: Cannot deserialize value of type `java.lang.String` from Array value (token `JsonToken.START_ARRAY`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 219] (through reference chain: org.example.petshopdesktop.api.dto.common.PageResponse["content"]->java.util.ArrayList[0]->org.example.petshopdesktop.api.dto.appointment.AppointmentResponse["petNames"]) | Context: Loading appointments for table display
[2026-03-08 10:12:33] [ERROR] EXCEPTION | Location: LoginController.btnLoginClicked | Type: ConnectException | Message: null | Context: Authentication attempt for username: admin
[2026-03-08 10:55:59] [ERROR] EXCEPTION | Location: AnalyticsController.loadAnalyticsData | Type: RuntimeException | Message: Access restricted. You don't have permission to perform this action. | Context: Loading analytics data
[2026-03-08 10:56:02] [ERROR] EXCEPTION | Location: SaleController.setupCreateSale | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.product.ProductResponse.getId()" is null | Context: Loading products
[2026-03-08 10:56:02] [ERROR] EXCEPTION | Location: SaleController.refreshSales | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.sale.SaleResponse.getId()" is null | Context: Loading sales
[2026-03-08 10:56:04] [ERROR] EXCEPTION | Location: ServiceController.displayServices | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.service.ServiceResponse.getId()" is null | Context: Fetching service data for table display
[2026-03-08 10:56:04] [ERROR] EXCEPTION | Location: PetController.displayPets | Type: NullPointerException | Message: Cannot invoke "java.lang.Long.intValue()" because the return value of "org.example.petshopdesktop.api.dto.pet.PetResponse.getId()" is null | Context: Fetching pet data for table display

View File

@@ -8,6 +8,9 @@ public class AdoptionRequest {
private LocalDate adoptionDate;
private String adoptionStatus;
public AdoptionRequest() {
}
public Long getPetId() {
return petId;
}

View File

@@ -9,6 +9,9 @@ public class AdoptionResponse {
private LocalDate adoptionDate;
private String adoptionStatus;
public AdoptionResponse() {
}
public Long getId() {
return id;
}

View File

@@ -7,6 +7,9 @@ public class DailySales {
private LocalDate date;
private BigDecimal totalSales;
public DailySales() {
}
public LocalDate getDate() {
return date;
}

View File

@@ -11,6 +11,9 @@ public class DashboardResponse {
private List<DailySales> dailySales;
private List<TopProduct> topProducts;
public DashboardResponse() {
}
public BigDecimal getTotalRevenue() {
return totalRevenue;
}

View File

@@ -7,6 +7,9 @@ public class TopProduct {
private Integer quantitySold;
private BigDecimal totalRevenue;
public TopProduct() {
}
public String getProductName() {
return productName;
}

View File

@@ -12,6 +12,9 @@ public class AppointmentRequest {
private LocalTime appointmentTime;
private String appointmentStatus;
public AppointmentRequest() {
}
public List<Long> getPetIds() {
return petIds;
}

View File

@@ -12,6 +12,9 @@ public class AppointmentResponse {
private LocalTime appointmentTime;
private String appointmentStatus;
public AppointmentResponse() {
}
public Long getId() {
return id;
}

View File

@@ -5,6 +5,9 @@ public class LoginResponse {
private String username;
private String role;
public LoginResponse() {
}
public String getToken() {
return token;
}

View File

@@ -5,6 +5,9 @@ public class UserInfoResponse {
private String username;
private String role;
public UserInfoResponse() {
}
public Long getId() {
return id;
}

View File

@@ -4,6 +4,9 @@ public class DropdownOption {
private Long id;
private String label;
public DropdownOption() {
}
public Long getId() {
return id;
}

View File

@@ -1,15 +1,27 @@
package org.example.petshopdesktop.api.dto.common;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class PageResponse<T> {
private List<T> content;
@JsonProperty("number")
private int pageNumber;
@JsonProperty("size")
private int pageSize;
private long totalElements;
private int totalPages;
private boolean last;
public PageResponse() {
}
public List<T> getContent() {
return content;
}

View File

@@ -6,6 +6,9 @@ public class InventoryRequest {
private Integer stockQuantity;
private Integer reorderLevel;
public InventoryRequest() {
}
public Long getProductId() {
return productId;
}

View File

@@ -8,6 +8,9 @@ public class InventoryResponse {
private Integer stockQuantity;
private Integer reorderLevel;
public InventoryResponse() {
}
public Long getId() {
return id;
}

View File

@@ -13,6 +13,9 @@ public class PetRequest {
private BigDecimal price;
private String petStatus;
public PetRequest() {
}
public String getPetName() {
return petName;
}

View File

@@ -14,6 +14,9 @@ public class PetResponse {
private BigDecimal price;
private String petStatus;
public PetResponse() {
}
public Long getId() {
return id;
}

View File

@@ -8,6 +8,9 @@ public class ProductRequest {
private BigDecimal price;
private String description;
public ProductRequest() {
}
public String getProductName() {
return productName;
}

View File

@@ -9,6 +9,9 @@ public class ProductResponse {
private BigDecimal price;
private String description;
public ProductResponse() {
}
public Long getId() {
return id;
}

View File

@@ -5,7 +5,10 @@ import java.math.BigDecimal;
public class ProductSupplierRequest {
private Long productId;
private Long supplierId;
private BigDecimal supplierPrice;
private BigDecimal cost;
public ProductSupplierRequest() {
}
public Long getProductId() {
return productId;
@@ -23,11 +26,11 @@ public class ProductSupplierRequest {
this.supplierId = supplierId;
}
public BigDecimal getSupplierPrice() {
return supplierPrice;
public BigDecimal getCost() {
return cost;
}
public void setSupplierPrice(BigDecimal supplierPrice) {
this.supplierPrice = supplierPrice;
public void setCost(BigDecimal cost) {
this.cost = cost;
}
}

View File

@@ -3,19 +3,13 @@ package org.example.petshopdesktop.api.dto.productsupplier;
import java.math.BigDecimal;
public class ProductSupplierResponse {
private Long id;
private Long productId;
private Long supplierId;
private String productName;
private String supplierName;
private BigDecimal supplierPrice;
private BigDecimal cost;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
public ProductSupplierResponse() {
}
public Long getProductId() {
@@ -50,11 +44,11 @@ public class ProductSupplierResponse {
this.supplierName = supplierName;
}
public BigDecimal getSupplierPrice() {
return supplierPrice;
public BigDecimal getCost() {
return cost;
}
public void setSupplierPrice(BigDecimal supplierPrice) {
this.supplierPrice = supplierPrice;
public void setCost(BigDecimal cost) {
this.cost = cost;
}
}

View File

@@ -11,6 +11,9 @@ public class PurchaseOrderResponse {
private String orderStatus;
private BigDecimal totalAmount;
public PurchaseOrderResponse() {
}
public Long getId() {
return id;
}

View File

@@ -7,6 +7,9 @@ public class SaleItemRequest {
private Integer quantity;
private BigDecimal unitPrice;
public SaleItemRequest() {
}
public Long getProductId() {
return productId;
}

View File

@@ -9,6 +9,9 @@ public class SaleItemResponse {
private BigDecimal unitPrice;
private BigDecimal lineTotal;
public SaleItemResponse() {
}
public Long getId() {
return id;
}

View File

@@ -9,6 +9,9 @@ public class SaleRequest {
private Boolean isRefund;
private Long originalSaleId;
public SaleRequest() {
}
public Long getStoreId() {
return storeId;
}

View File

@@ -15,6 +15,9 @@ public class SaleResponse {
private Long originalSaleId;
private List<SaleItemResponse> items;
public SaleResponse() {
}
public Long getId() {
return id;
}

View File

@@ -7,6 +7,9 @@ public class ServiceRequest {
private BigDecimal price;
private String description;
public ServiceRequest() {
}
public String getServiceName() {
return serviceName;
}

View File

@@ -8,6 +8,9 @@ public class ServiceResponse {
private BigDecimal price;
private String description;
public ServiceResponse() {
}
public Long getId() {
return id;
}

View File

@@ -7,6 +7,9 @@ public class SupplierRequest {
private String email;
private String address;
public SupplierRequest() {
}
public String getSupplierName() {
return supplierName;
}

View File

@@ -8,6 +8,9 @@ public class SupplierResponse {
private String email;
private String address;
public SupplierResponse() {
}
public Long getId() {
return id;
}

View File

@@ -8,6 +8,9 @@ public class UserRequest {
private String role;
private Boolean active;
public UserRequest() {
}
public String getUsername() {
return username;
}

View File

@@ -10,6 +10,9 @@ public class UserResponse {
private Boolean active;
private LocalDateTime createdAt;
public UserResponse() {
}
public Long getId() {
return id;
}

View File

@@ -43,11 +43,11 @@ public class ProductSupplierApi {
return apiClient.post("/api/v1/product-suppliers", request, ProductSupplierResponse.class);
}
public ProductSupplierResponse updateProductSupplier(Long id, ProductSupplierRequest request) throws Exception {
return apiClient.put("/api/v1/product-suppliers/" + id, request, ProductSupplierResponse.class);
public ProductSupplierResponse updateProductSupplier(Long productId, Long supplierId, ProductSupplierRequest request) throws Exception {
return apiClient.put("/api/v1/product-suppliers/" + productId + "/" + supplierId, request, ProductSupplierResponse.class);
}
public void deleteProductSuppliers(List<Long> ids) throws Exception {
apiClient.deleteWithBody("/api/v1/product-suppliers", new BulkDeleteRequest(ids));
public void deleteProductSupplier(Long productId, Long supplierId) throws Exception {
apiClient.delete("/api/v1/product-suppliers/" + productId + "/" + supplierId);
}
}

View File

@@ -192,24 +192,36 @@ public class ProductSupplierController {
//if confirmed, start deletion
if (result.isPresent() && result.get() == ButtonType.OK) {
List<Long> ids = selectedProductSuppliers.stream()
.map(ps -> (long) ps.getSupId())
.collect(Collectors.toList());
int deleteCount = 0;
Exception lastException = null;
try {
ProductSupplierApi.getInstance().deleteProductSuppliers(ids);
for (ProductSupplierDTO ps : selectedProductSuppliers) {
try {
ProductSupplierApi.getInstance().deleteProductSupplier(
(long) ps.getProdId(),
(long) ps.getSupId()
);
deleteCount++;
} catch (Exception e) {
lastException = e;
ActivityLogger.getInstance().logException(
"ProductSupplierController.btnDeleteClicked",
e,
"Deleting product-supplier with productId=" + ps.getProdId() + ", supplierId=" + ps.getSupId());
}
}
if (deleteCount > 0) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Database Operation Confirmed");
alert.setContentText("Successfully deleted " + ids.size() + " product-supplier(s)");
alert.setContentText("Successfully deleted " + deleteCount + " product-supplier(s)");
alert.showAndWait();
} catch (Exception e) {
ActivityLogger.getInstance().logException(
"ProductSupplierController.btnDeleteClicked",
e,
"Deleting product-suppliers");
}
if (lastException != null && deleteCount < selectedProductSuppliers.size()) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Delete Operation Failed");
alert.setContentText(e.getMessage());
alert.setHeaderText("Delete Operation Partially Failed");
alert.setContentText("Deleted " + deleteCount + " of " + selectedProductSuppliers.size() + " product-supplier(s). Last error: " + lastException.getMessage());
alert.showAndWait();
}
@@ -286,7 +298,7 @@ public class ProductSupplierController {
response.getProductId().intValue(),
response.getSupplierName(),
response.getProductName(),
response.getSupplierPrice().doubleValue()
response.getCost().doubleValue()
);
}

View File

@@ -46,7 +46,6 @@ public class ProductSupplierDialogController {
private String mode = null;
private int selectedSupId = -1;
private int selectedProdId = -1;
private Long selectedId = null;
/**
* add event listeners to buttons and set up combobox
@@ -169,7 +168,7 @@ public class ProductSupplierDialogController {
if (mode.equals("Add")) {
ProductSupplierApi.getInstance().createProductSupplier(request);
} else {
ProductSupplierApi.getInstance().updateProductSupplier(selectedId, request);
ProductSupplierApi.getInstance().updateProductSupplier((long) selectedProdId, (long) selectedSupId, request);
}
Platform.runLater(() -> {
@@ -209,7 +208,7 @@ public class ProductSupplierDialogController {
request.setSupplierId(cbSupplier.getSelectionModel().getSelectedItem().getId());
request.setProductId(cbProduct.getSelectionModel().getSelectedItem().getId());
try {
request.setSupplierPrice(new BigDecimal(txtCost.getText()));
request.setCost(new BigDecimal(txtCost.getText()));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid cost format");
}
@@ -266,7 +265,6 @@ public class ProductSupplierDialogController {
public void setSelectedIds(int supId, int prodId){
this.selectedSupId = supId;
this.selectedProdId = prodId;
this.selectedId = (long) supId;
}
}