Fix refund flow
This commit is contained in:
@@ -372,6 +372,11 @@ public class SaleController {
|
|||||||
private void openRefundDialog() {
|
private void openRefundDialog() {
|
||||||
try {
|
try {
|
||||||
SaleLineItem selectedSale = tvSales.getSelectionModel().getSelectedItem();
|
SaleLineItem selectedSale = tvSales.getSelectionModel().getSelectedItem();
|
||||||
|
if (selectedSale != null && selectedSale.isRefund()) {
|
||||||
|
showError("Refund", "Select an original sale, not an existing refund.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
FXMLLoader loader = new FXMLLoader(getClass().getResource(
|
||||||
"/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml"));
|
"/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml"));
|
||||||
Stage dialog = new Stage();
|
Stage dialog = new Stage();
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ public class RefundDialogController {
|
|||||||
private Button btnCancel;
|
private Button btnCancel;
|
||||||
|
|
||||||
private SaleResponse currentSale;
|
private SaleResponse currentSale;
|
||||||
|
private final List<SaleItemResponse> baseOriginalItems = new ArrayList<>();
|
||||||
|
private final ObservableList<SaleItemResponse> originalItems = FXCollections.observableArrayList();
|
||||||
private final ObservableList<RefundItem> refundItems = FXCollections.observableArrayList();
|
private final ObservableList<RefundItem> refundItems = FXCollections.observableArrayList();
|
||||||
private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA);
|
private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA);
|
||||||
|
|
||||||
@@ -102,6 +104,7 @@ public class RefundDialogController {
|
|||||||
colOriginalQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
|
colOriginalQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
|
||||||
colOriginalUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
|
colOriginalUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
|
||||||
colOriginalTotal.setCellValueFactory(new PropertyValueFactory<>("lineTotal"));
|
colOriginalTotal.setCellValueFactory(new PropertyValueFactory<>("lineTotal"));
|
||||||
|
tvOriginalItems.setItems(originalItems);
|
||||||
tvOriginalItems.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
|
tvOriginalItems.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
|
||||||
|
|
||||||
colRefundProduct.setCellValueFactory(new PropertyValueFactory<>("productName"));
|
colRefundProduct.setCellValueFactory(new PropertyValueFactory<>("productName"));
|
||||||
@@ -143,6 +146,11 @@ public class RefundDialogController {
|
|||||||
try {
|
try {
|
||||||
List<SaleResponse> allSales = SaleApi.getInstance().listSales(0, 1000, null);
|
List<SaleResponse> allSales = SaleApi.getInstance().listSales(0, 1000, null);
|
||||||
currentSale = SaleApi.getInstance().getSale(saleId);
|
currentSale = SaleApi.getInstance().getSale(saleId);
|
||||||
|
if (Boolean.TRUE.equals(currentSale.getIsRefund())) {
|
||||||
|
clearLoadedSale();
|
||||||
|
showError("Load Sale", "Select an original sale, not a refund record.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
List<SaleResponse> previousRefunds = allSales.stream()
|
List<SaleResponse> previousRefunds = allSales.stream()
|
||||||
.filter(s -> Boolean.TRUE.equals(s.getIsRefund()) && saleId.equals(s.getOriginalSaleId()))
|
.filter(s -> Boolean.TRUE.equals(s.getIsRefund()) && saleId.equals(s.getOriginalSaleId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@@ -161,10 +169,13 @@ public class RefundDialogController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tvOriginalItems.setItems(FXCollections.observableArrayList(refundableItems));
|
baseOriginalItems.clear();
|
||||||
|
baseOriginalItems.addAll(copySaleItems(refundableItems));
|
||||||
|
originalItems.setAll(copySaleItems(refundableItems));
|
||||||
cbPaymentMethod.getSelectionModel().select(currentSale.getPaymentMethod());
|
cbPaymentMethod.getSelectionModel().select(currentSale.getPaymentMethod());
|
||||||
|
|
||||||
refundItems.clear();
|
refundItems.clear();
|
||||||
|
updateOriginalItemAvailability();
|
||||||
updateRefundTotal();
|
updateRefundTotal();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -215,12 +226,8 @@ public class RefundDialogController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
refundItems.add(new RefundItem(
|
addOrMergeRefundItem(selected, quantity);
|
||||||
selected.getProdId().intValue(),
|
updateOriginalItemAvailability();
|
||||||
selected.getProductName(),
|
|
||||||
quantity,
|
|
||||||
selected.getUnitPrice().doubleValue()
|
|
||||||
));
|
|
||||||
updateRefundTotal();
|
updateRefundTotal();
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
@@ -234,6 +241,7 @@ public class RefundDialogController {
|
|||||||
RefundItem selected = tvRefundItems.getSelectionModel().getSelectedItem();
|
RefundItem selected = tvRefundItems.getSelectionModel().getSelectedItem();
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
refundItems.remove(selected);
|
refundItems.remove(selected);
|
||||||
|
updateOriginalItemAvailability();
|
||||||
updateRefundTotal();
|
updateRefundTotal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,6 +317,83 @@ public class RefundDialogController {
|
|||||||
closeDialog();
|
closeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void clearLoadedSale() {
|
||||||
|
currentSale = null;
|
||||||
|
lblSaleInfo.setText("");
|
||||||
|
baseOriginalItems.clear();
|
||||||
|
originalItems.clear();
|
||||||
|
refundItems.clear();
|
||||||
|
updateRefundTotal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addOrMergeRefundItem(SaleItemResponse selected, int quantity) {
|
||||||
|
for (int i = 0; i < refundItems.size(); i++) {
|
||||||
|
RefundItem existing = refundItems.get(i);
|
||||||
|
if (existing.getProdId() == selected.getProdId().intValue()) {
|
||||||
|
refundItems.set(i, new RefundItem(
|
||||||
|
existing.getProdId(),
|
||||||
|
existing.getProductName(),
|
||||||
|
existing.getQuantity() + quantity,
|
||||||
|
existing.getUnitPrice()
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refundItems.add(new RefundItem(
|
||||||
|
selected.getProdId().intValue(),
|
||||||
|
selected.getProductName(),
|
||||||
|
quantity,
|
||||||
|
selected.getUnitPrice().doubleValue()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateOriginalItemAvailability() {
|
||||||
|
if (currentSale == null) {
|
||||||
|
baseOriginalItems.clear();
|
||||||
|
originalItems.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Long, Integer> pendingRefunds = new HashMap<>();
|
||||||
|
for (RefundItem refundItem : refundItems) {
|
||||||
|
pendingRefunds.merge((long) refundItem.getProdId(), refundItem.getQuantity(), Integer::sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SaleItemResponse> refreshedItems = new ArrayList<>();
|
||||||
|
for (SaleItemResponse originalItem : baseOriginalItems) {
|
||||||
|
SaleItemResponse refreshedItem = copySaleItem(originalItem);
|
||||||
|
int pending = pendingRefunds.getOrDefault(refreshedItem.getProdId(), 0);
|
||||||
|
refreshedItem.setQuantity(Math.max(0, refreshedItem.getQuantity() - pending));
|
||||||
|
if (refreshedItem.getQuantity() > 0) {
|
||||||
|
refreshedItems.add(refreshedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
originalItems.setAll(refreshedItems);
|
||||||
|
tvOriginalItems.getSelectionModel().clearSelection();
|
||||||
|
tvOriginalItems.refresh();
|
||||||
|
tvRefundItems.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SaleItemResponse> copySaleItems(List<SaleItemResponse> items) {
|
||||||
|
List<SaleItemResponse> copies = new ArrayList<>();
|
||||||
|
for (SaleItemResponse item : items) {
|
||||||
|
copies.add(copySaleItem(item));
|
||||||
|
}
|
||||||
|
return copies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SaleItemResponse copySaleItem(SaleItemResponse source) {
|
||||||
|
SaleItemResponse copy = new SaleItemResponse();
|
||||||
|
copy.setSaleItemId(source.getSaleItemId());
|
||||||
|
copy.setProdId(source.getProdId());
|
||||||
|
copy.setProductName(source.getProductName());
|
||||||
|
copy.setQuantity(source.getQuantity());
|
||||||
|
copy.setUnitPrice(source.getUnitPrice());
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateRefundTotal() {
|
private void updateRefundTotal() {
|
||||||
double total = refundItems.stream().mapToDouble(RefundItem::getTotal).sum();
|
double total = refundItems.stream().mapToDouble(RefundItem::getTotal).sum();
|
||||||
lblRefundTotal.setText(currency.format(total));
|
lblRefundTotal.setText(currency.format(total));
|
||||||
|
|||||||
Reference in New Issue
Block a user