diff --git a/src/main/java/org/chainoptim/desktop/AppModule.java b/src/main/java/org/chainoptim/desktop/AppModule.java index af9b8277..9ef2e42d 100644 --- a/src/main/java/org/chainoptim/desktop/AppModule.java +++ b/src/main/java/org/chainoptim/desktop/AppModule.java @@ -156,8 +156,8 @@ protected void configure() { // - Client bind(ClientService.class).to(ClientServiceImpl.class); bind(ClientWriteService.class).to(ClientWriteServiceImpl.class); - bind(ClientOrderService.class).to(ClientOrderServiceImpl.class); - bind(ClientOrderWriteService.class).to(ClientOrderWriteServiceImpl.class); + bind(ClientOrdersService.class).to(ClientOrdersServiceImpl.class); + bind(ClientOrdersWriteService.class).to(ClientOrdersWriteServiceImpl.class); // - SC Analysis bind(ProductProductionGraphService.class).to(ProductProductionGraphServiceImpl.class); diff --git a/src/main/java/org/chainoptim/desktop/features/client/controller/ClientOrdersController.java b/src/main/java/org/chainoptim/desktop/features/client/controller/ClientOrdersController.java index e9215203..41fcca84 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/controller/ClientOrdersController.java +++ b/src/main/java/org/chainoptim/desktop/features/client/controller/ClientOrdersController.java @@ -1,167 +1,680 @@ package org.chainoptim.desktop.features.client.controller; +import org.chainoptim.desktop.core.context.TenantContext; +import org.chainoptim.desktop.core.user.model.User; +import org.chainoptim.desktop.features.client.service.ClientOrdersService; +import org.chainoptim.desktop.features.client.service.ClientOrdersWriteService; +import org.chainoptim.desktop.features.product.model.Product; +import org.chainoptim.desktop.features.client.dto.CreateClientOrderDTO; +import org.chainoptim.desktop.features.client.dto.UpdateClientOrderDTO; import org.chainoptim.desktop.features.client.model.Client; import org.chainoptim.desktop.features.client.model.ClientOrder; -import org.chainoptim.desktop.features.client.service.ClientOrderService; +import org.chainoptim.desktop.shared.confirmdialog.controller.GenericConfirmDialogController; +import org.chainoptim.desktop.shared.confirmdialog.controller.RunnableConfirmDialogActionListener; +import org.chainoptim.desktop.shared.confirmdialog.model.ConfirmDialogInput; +import org.chainoptim.desktop.shared.enums.Feature; +import org.chainoptim.desktop.shared.enums.OperationOutcome; +import org.chainoptim.desktop.shared.enums.OrderStatus; import org.chainoptim.desktop.shared.fallback.FallbackManager; import org.chainoptim.desktop.shared.httphandling.Result; +import org.chainoptim.desktop.shared.search.controller.PageSelectorController; +import org.chainoptim.desktop.shared.search.model.PaginatedResults; +import org.chainoptim.desktop.shared.search.model.SearchOptions; +import org.chainoptim.desktop.shared.search.model.SearchOptionsConfiguration; +import org.chainoptim.desktop.shared.search.model.SearchParams; +import org.chainoptim.desktop.shared.table.TableToolbarController; +import org.chainoptim.desktop.shared.table.edit.cell.ComboBoxEditableCell; +import org.chainoptim.desktop.shared.table.edit.cell.DateTimePickerCell; +import org.chainoptim.desktop.shared.table.edit.cell.EditableCell; +import org.chainoptim.desktop.shared.table.model.TableData; +import org.chainoptim.desktop.shared.table.util.SelectProductLoader; +import org.chainoptim.desktop.shared.table.util.TableConfigurer; +import org.chainoptim.desktop.shared.toast.controller.ToastManager; +import org.chainoptim.desktop.shared.toast.model.ToastInfo; import org.chainoptim.desktop.shared.util.DataReceiver; import org.chainoptim.desktop.shared.util.resourceloader.CommonViewsLoader; import com.google.inject.Inject; - -import java.time.LocalDateTime; - import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.MapChangeListener; import javafx.fxml.FXML; +import javafx.scene.control.ScrollPane; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; -import javafx.scene.control.cell.PropertyValueFactory; -import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.layout.StackPane; -import javafx.util.Callback; -import javafx.util.converter.FloatStringConverter; -import javafx.util.converter.IntegerStringConverter; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; public class ClientOrdersController implements DataReceiver { - private final ClientOrderService clientOrderService; - private final FallbackManager fallbackManager; + // Services + private final ClientOrdersService clientOrdersService; + private final ClientOrdersWriteService clientOrdersWriteService; private final CommonViewsLoader commonViewsLoader; + private final ToastManager toastManager; + + // Controllers + private TableToolbarController tableToolbarController; + private PageSelectorController pageSelectorController; + private final SelectProductLoader selectProductLoader; + private GenericConfirmDialogController> confirmClientOrderUpdateController; + private GenericConfirmDialogController> confirmClientOrderDeleteController; + private GenericConfirmDialogController> confirmClientOrderCreateController; + + // State + private final FallbackManager fallbackManager; + private final SearchParams searchParams; private Client client; - private List clientOrders; + private final List statusOptions = Arrays.asList(OrderStatus.values()); + private long totalRowsCount; + private int newOrderCount = 0; + private final List selectedRowsIndices = new ArrayList<>(); + private final SimpleIntegerProperty selectedCount = new SimpleIntegerProperty(0); + private final BooleanProperty isEditMode = new SimpleBooleanProperty(false); + private final SimpleBooleanProperty isNewOrderMode = new SimpleBooleanProperty(false); + + // Confirm Dialog Listeners + private RunnableConfirmDialogActionListener> confirmDialogUpdateListener; + private RunnableConfirmDialogActionListener> confirmDialogDeleteListener; + private RunnableConfirmDialogActionListener> confirmDialogCreateListener; + // FXML + @FXML + private StackPane tableToolbarContainer; + @FXML + private ScrollPane clientOrdersScrollPane; @FXML - private StackPane stackPane; + private TableView> tableView; @FXML - private TableView tableView; + private TableColumn, Boolean> selectRowColumn; @FXML - private TableColumn orderIdColumn; + private TableColumn, Integer> orderIdColumn; @FXML - private TableColumn clientIdColumn; + private TableColumn, String> companyIdColumn; @FXML - private TableColumn productIdColumn; + private TableColumn, String> clientNameColumn; @FXML - private TableColumn quantityColumn; + private TableColumn, String> productNameColumn; @FXML - private TableColumn statusColumn; + private TableColumn, Float> quantityColumn; @FXML - private TableColumn orderDateColumn; + private TableColumn, Float> deliveredQuantityColumn; @FXML - private TableColumn estimatedDeliveryDateColumn; + private TableColumn, OrderStatus> statusColumn; @FXML - private TableColumn deliveryDateColumn; + private TableColumn, LocalDateTime> orderDateColumn; @FXML - private StackPane fallbackContainer; + private TableColumn, LocalDateTime> estimatedDeliveryDateColumn; + @FXML + private TableColumn, LocalDateTime> deliveryDateColumn; + @FXML + private StackPane pageSelectorContainer; + @FXML + private StackPane confirmUpdateDialogContainer; + @FXML + private StackPane confirmDeleteDialogContainer; + @FXML + private StackPane confirmCreateDialogContainer; + @Inject - public ClientOrdersController(FallbackManager fallbackManager, - ClientOrderService clientOrderService, - CommonViewsLoader commonViewsLoader) { - this.fallbackManager = fallbackManager; - this.clientOrderService = clientOrderService; + public ClientOrdersController(ClientOrdersService clientOrdersService, + ClientOrdersWriteService clientOrdersWriteService, + CommonViewsLoader commonViewsLoader, + SelectProductLoader selectProductLoader, + ToastManager toastManager, + FallbackManager fallbackManager, + SearchParams searchParams) { + this.clientOrdersService = clientOrdersService; + this.clientOrdersWriteService = clientOrdersWriteService; this.commonViewsLoader = commonViewsLoader; + this.toastManager = toastManager; + this.selectProductLoader = selectProductLoader; + this.fallbackManager = fallbackManager; + this.searchParams = searchParams; } @Override public void setData(Client client) { - commonViewsLoader.loadFallbackManager(fallbackContainer); this.client = client; + + searchParams.setItemsPerPage(20); + SearchOptions searchOptions = SearchOptionsConfiguration.getSearchOptions(Feature.SUPPLIER_ORDER); + + tableToolbarController = commonViewsLoader.initializeTableToolbar(tableToolbarContainer); + tableToolbarController.initialize( + searchParams, + searchOptions.getFilterOptions(), + searchOptions.getSortOptions(), + () -> loadClientOrders(client.getId())); + pageSelectorController = commonViewsLoader.loadPageSelector(pageSelectorContainer); + selectProductLoader.initialize(); + + TableConfigurer.configureTableView(tableView, selectRowColumn); + configureTableColumns(); + setUpListeners(); + loadConfirmDialogs(); + loadClientOrders(client.getId()); } + // Loading + private void loadConfirmDialogs() { + confirmClientOrderCreateController = commonViewsLoader.loadConfirmDialog(confirmCreateDialogContainer); + confirmClientOrderCreateController.setActionListener(confirmDialogCreateListener); + closeConfirmCreateDialog(); + + confirmClientOrderUpdateController = commonViewsLoader.loadConfirmDialog(confirmUpdateDialogContainer); + confirmClientOrderUpdateController.setActionListener(confirmDialogUpdateListener); + closeConfirmUpdateDialog(); + + confirmClientOrderDeleteController = commonViewsLoader.loadConfirmDialog(confirmDeleteDialogContainer); + confirmClientOrderDeleteController.setActionListener(confirmDialogDeleteListener); + closeConfirmDeleteDialog(); + } + + // Configuration + // - Table columns + private void configureTableColumns() { + // Bind columns to data + selectRowColumn.setCellValueFactory(data -> data.getValue().isSelectedProperty()); + orderIdColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getId())); + companyIdColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getCompanyId() != null ? data.getValue().getData().getCompanyId() : "N/A")); + clientNameColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(this.client.getName())); + productNameColumn.setCellValueFactory(data -> { + Product product = data.getValue().getData().getProduct(); + String productName = product != null ? product.getName() : "N/A"; + return new SimpleObjectProperty<>(productName); + }); + quantityColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getQuantity())); + deliveredQuantityColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getDeliveredQuantity())); + statusColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getStatus())); + orderDateColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getOrderDate())); + estimatedDeliveryDateColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getEstimatedDeliveryDate())); + deliveryDateColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getData().getDeliveryDate())); + + configureColumnCellFactories(); + } + + private void configureColumnCellFactories() { + companyIdColumn.setCellFactory(column -> new EditableCell, String>( + isEditMode, selectedRowsIndices, String::toString) { + @Override + protected void commitChange(TableData item, String newValue) { + item.getData().setCompanyId(newValue); + } + }); + quantityColumn.setCellFactory(column -> new EditableCell, Float>( + isEditMode, selectedRowsIndices, Float::parseFloat) { + @Override + protected void commitChange(TableData item, Float newValue) { + item.getData().setQuantity(newValue); + } + }); + deliveredQuantityColumn.setCellFactory(column -> new EditableCell, Float>( + isEditMode, selectedRowsIndices, Float::parseFloat) { + @Override + protected void commitChange(TableData item, Float newValue) { + item.getData().setDeliveredQuantity(newValue); + } + }); + estimatedDeliveryDateColumn.setCellFactory(column -> new DateTimePickerCell, LocalDateTime>( + isEditMode, selectedRowsIndices, true) { + @Override + protected void commitChange(TableData item, LocalDateTime newValue) { + item.getData().setEstimatedDeliveryDate(newValue); + } + }); + + deliveryDateColumn.setCellFactory(column -> new DateTimePickerCell, LocalDateTime>( + isEditMode, selectedRowsIndices, true) { + @Override + protected void commitChange(TableData item, LocalDateTime newValue) { + item.getData().setDeliveryDate(newValue); + } + }); + orderDateColumn.setCellFactory(column -> new DateTimePickerCell, LocalDateTime>( + isEditMode, selectedRowsIndices, false){}); + + statusColumn.setCellFactory(column -> new ComboBoxEditableCell, OrderStatus>( + isEditMode, selectedRowsIndices, null, statusOptions) { + @Override + protected void commitChange(TableData item, OrderStatus newValue) { + item.getData().setStatus(newValue); + } + }); + productNameColumn.setCellFactory(column -> new ComboBoxEditableCell, String>( + isEditMode, selectedRowsIndices, null, selectProductLoader.getProductsName()) { + @Override + protected void commitChange(TableData item, String newValue) { + Product product = new Product(); + product.setId(selectProductLoader.getProductIdByName(newValue)); + product.setName(newValue); + item.getData().setProduct(product); + } + }); + } + + // - Listeners + private void setUpListeners() { + setUpSearchListeners(); + setUpTableToolbarListeners(); + setUpConfirmDialogListeners(); + } + + private void setUpSearchListeners() { + searchParams.getPageProperty().addListener((observable, oldPage, newPage) -> loadClientOrders(client.getId())); + searchParams.getSortOptionProperty().addListener((observable, oldValue, newValue) -> loadClientOrders(client.getId())); + searchParams.getAscendingProperty().addListener((observable, oldValue, newValue) -> loadClientOrders(client.getId())); + searchParams.getSearchQueryProperty().addListener((observable, oldValue, newValue) -> loadClientOrders(client.getId())); + searchParams.getFiltersProperty().addListener((MapChangeListener.Change change) -> { + if (searchParams.getFiltersProperty().entrySet().size() == 1) { // Allow only one filter at a time + loadClientOrders(client.getId()); + } + }); + } + + private void setUpTableToolbarListeners() { + selectedCount.addListener((obs, oldCount, newCount) -> { + boolean isAnyRowSelected = newCount.intValue() > 0; + tableToolbarController.toggleButtonVisibilityOnSelection(isAnyRowSelected); + }); + + // Listen to the toolbar buttons + tableToolbarController.getCancelRowSelectionButton().setOnAction(e -> cancelSelectionsAndEdit()); + tableToolbarController.getEditSelectedRowsButton().setOnAction(e -> editSelectedRows()); + tableToolbarController.getSaveChangesButton().setOnAction(e -> { + if (isNewOrderMode.get()) { + openConfirmCreateDialog(); + } else { + openConfirmUpdateDialog(selectedRowsIndices); + } + }); + tableToolbarController.getDeleteSelectedRowsButton().setOnAction(e -> openConfirmDeleteDialog(selectedRowsIndices));; + tableToolbarController.getCreateNewOrderButton().setOnAction(e -> addNewOrder()); + } + + private void setUpConfirmDialogListeners() { + Consumer> onConfirmDelete = this::handleDeleteOrders; + Runnable onCancelDelete = this::closeConfirmDeleteDialog; + confirmDialogDeleteListener = new RunnableConfirmDialogActionListener<>(onConfirmDelete, onCancelDelete); + + Consumer> onConfirmUpdate = this::handleUpdateOrders; + Runnable onCancelUpdate = this::closeConfirmUpdateDialog; + confirmDialogUpdateListener = new RunnableConfirmDialogActionListener<>(onConfirmUpdate, onCancelUpdate); + + Consumer> onConfirmCreate = this::handleCreateOrders; + Runnable onCancelCreate = this::closeConfirmCreateDialog; + confirmDialogCreateListener = new RunnableConfirmDialogActionListener<>(onConfirmCreate, onCancelCreate); + } + + private void setUpRowListeners(TableData clientOrder) { + // Add listener to the selectedProperty + clientOrder.isSelectedProperty().addListener((obs, wasSelected, isSelected) -> { + if (Boolean.TRUE.equals(isSelected)) { + selectedRowsIndices.add(tableView.getItems().indexOf(clientOrder)); + } else { + selectedRowsIndices.remove(Integer.valueOf(tableView.getItems().indexOf(clientOrder))); + } + selectedCount.set(selectedRowsIndices.size()); + }); + } + + // Data loading private void loadClientOrders(Integer clientId) { fallbackManager.reset(); fallbackManager.setLoading(true); - clientOrderService.getClientOrdersByOrganizationId(clientId) + User currentUser = TenantContext.getCurrentUser(); + if (currentUser == null) { + fallbackManager.setLoading(false); + return; + } + + clientOrdersService.getClientOrdersByClientIdAdvanced(clientId, searchParams) .thenApply(this::handleOrdersResponse) .exceptionally(this::handleOrdersException); } - private Result> handleOrdersResponse(Result> result) { + private Result> handleOrdersResponse(Result> result) { Platform.runLater(() -> { if (result.getError() != null) { - fallbackManager.setErrorMessage("Failed to load client orders."); + fallbackManager.setErrorMessage("No orders found"); return; } - this.clientOrders = result.getData(); + PaginatedResults paginatedResults = result.getData(); fallbackManager.setLoading(false); - System.out.println("Orders received: " + clientOrders); - configureTableView(); - bindDataToTableView(); - setEditEvents(); + totalRowsCount = paginatedResults.getTotalCount(); + pageSelectorController.initialize(searchParams, totalRowsCount); + + tableView.getItems().clear(); + if (paginatedResults.results.isEmpty()) { + fallbackManager.setNoResults(true); + return; + } + + for (ClientOrder clientOrder : paginatedResults.results) { + ClientOrder oldData = new ClientOrder(clientOrder); + TableData tableRow = new TableData<>(clientOrder, oldData, new SimpleBooleanProperty(false)); + setUpRowListeners(tableRow); + tableView.getItems().add(tableRow); + } }); return result; } - private Result> handleOrdersException(Throwable ex) { + private Result> handleOrdersException(Throwable ex) { Platform.runLater(() -> fallbackManager.setErrorMessage("Failed to load client orders.")); return new Result<>(); } - private void configureTableView() { - tableView.setEditable(true); - clientIdColumn.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter())); - productIdColumn.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter())); - quantityColumn.setCellFactory(TextFieldTableCell.forTableColumn(new FloatStringConverter())); - statusColumn.setCellFactory(TextFieldTableCell.forTableColumn()); + // UI Actions + private void addNewOrder() { + isNewOrderMode.set(true); + tableToolbarController.toggleButtonVisibilityOnCreate(isNewOrderMode.get()); - tableView.setMaxHeight(Double.MAX_VALUE); + ClientOrder newOrder = new ClientOrder(); + TableData newOrderRow = new TableData<>(newOrder, newOrder, new SimpleBooleanProperty(false)); + tableView.getItems().addFirst(newOrderRow); + newOrderRow.setSelected(true); - // Set the column resize policy and their minimum width - tableView.setColumnResizePolicy(new Callback() { - @Override - public Boolean call(TableView.ResizeFeatures param) { - return TableView.CONSTRAINED_RESIZE_POLICY.call(param) || Boolean.TRUE; + selectedRowsIndices.clear(); + for (int i = 0; i <= newOrderCount; i++) { + selectedRowsIndices.add(i); + } + newOrderCount++; + isEditMode.set(true); + selectRowColumn.setEditable(false); + tableView.refresh(); + } + + private void editSelectedRows() { + tableToolbarController.toggleButtonVisibilityOnEdit(true); + isEditMode.set(true); + for (Integer index : selectedRowsIndices) { + TableData tableRow = tableView.getItems().get(index); + ClientOrder oldOrder = new ClientOrder(tableRow.getData()); + oldOrder.setProduct(new Product(tableRow.getData().getProduct())); + tableRow.setOldData(oldOrder); + } + selectRowColumn.setEditable(false); + tableView.refresh(); + } + + private void cancelSelectionsAndEdit() { + isEditMode.set(false); + tableView.getSelectionModel().clearSelection(); + + tableToolbarController.toggleButtonVisibilityOnCancel(); + + // Deselect all rows and clear recording array + List indicesToClear = new ArrayList<>(selectedRowsIndices); + for (Integer rowIndex : indicesToClear) { + TableData tableRow = tableView.getItems().get(rowIndex); + tableRow.setData(tableRow.getOldData()); + tableRow.setSelected(false); + } + selectedRowsIndices.clear(); + + // Delete created new orders + if (isNewOrderMode.get()) { + for (int i = 0; i < newOrderCount; i++) { + tableView.getItems().removeFirst(); } + isNewOrderMode.set(false); + newOrderCount = 0; + } + selectRowColumn.setEditable(true); + tableView.refresh(); + } + + // Confirm Dialogs + private void openConfirmCreateDialog() { + ConfirmDialogInput confirmDialogInput = new ConfirmDialogInput( + "Confirm Client Orders Create", + "Are you sure you want to create new orders?", + null); + List selectedOrders = new ArrayList<>(); + for (Integer index : selectedRowsIndices) { + selectedOrders.add(tableView.getItems().get(index).getData()); + } + confirmClientOrderCreateController.setData(selectedOrders, confirmDialogInput); + toggleDialogVisibility(confirmCreateDialogContainer, true); + } + + private void closeConfirmCreateDialog() { + toggleDialogVisibility(confirmCreateDialogContainer, false); + } + + private void openConfirmUpdateDialog(List selectedRowsIndices) { + ConfirmDialogInput confirmDialogInput = new ConfirmDialogInput( + "Confirm Client Orders Update", + "Are you sure you want to update selected orders?", + null); + List selectedOrders = new ArrayList<>(); + for (Integer index : selectedRowsIndices) { + selectedOrders.add(tableView.getItems().get(index).getData()); + } + confirmClientOrderUpdateController.setData(selectedOrders, confirmDialogInput); + toggleDialogVisibility(confirmUpdateDialogContainer, true); + } + + private void closeConfirmUpdateDialog() { + toggleDialogVisibility(confirmUpdateDialogContainer, false); + } + + private void openConfirmDeleteDialog(List selectedRowsIndices) { + ConfirmDialogInput confirmDialogInput = new ConfirmDialogInput( + "Confirm Client Orders Delete", + "Are you sure you want to delete selected orders?", + null); + List selectedOrders = new ArrayList<>(); + for (Integer index : selectedRowsIndices) { + selectedOrders.add(tableView.getItems().get(index).getData()); + } + confirmClientOrderDeleteController.setData(selectedOrders, confirmDialogInput); + toggleDialogVisibility(confirmDeleteDialogContainer, true); + } + + private void closeConfirmDeleteDialog() { + toggleDialogVisibility(confirmDeleteDialogContainer, false); + } + + private void toggleDialogVisibility(StackPane dialogContainer, boolean isVisible) { + dialogContainer.setVisible(isVisible); + dialogContainer.setManaged(isVisible); + } + + // Backend calls + // - Create + private void handleCreateOrders(List clientOrders) { + List createClientOrderDTOs = new ArrayList<>(); + for (ClientOrder order : clientOrders) { + CreateClientOrderDTO createClientOrderDTO = getCreateClientOrderDTO(order); + + createClientOrderDTOs.add(createClientOrderDTO); + } + + fallbackManager.reset(); + fallbackManager.setLoading(true); + + clientOrdersWriteService.createClientOrdersInBulk(createClientOrderDTOs) + .thenApply(this::handleCreateClientOrdersResponse) + .exceptionally(this::handleCreateClientOrdersException); + } + + private CreateClientOrderDTO getCreateClientOrderDTO(ClientOrder order) { + CreateClientOrderDTO createClientOrderDTO = new CreateClientOrderDTO(); + if (client == null || client.getOrganizationId() == null) { + throw new IllegalArgumentException("Client Organization ID is missing"); + } + createClientOrderDTO.setOrganizationId(client.getOrganizationId()); + createClientOrderDTO.setClientId(client.getId()); + createClientOrderDTO.setProductId(order.getProduct().getId()); + createClientOrderDTO.setQuantity(order.getQuantity()); + createClientOrderDTO.setDeliveredQuantity(order.getDeliveredQuantity()); + createClientOrderDTO.setOrderDate(order.getOrderDate()); + createClientOrderDTO.setEstimatedDeliveryDate(order.getEstimatedDeliveryDate()); + createClientOrderDTO.setDeliveryDate(order.getDeliveryDate()); + createClientOrderDTO.setStatus(order.getStatus()); + createClientOrderDTO.setCompanyId(order.getCompanyId()); + + return createClientOrderDTO; + } + + private Result> handleCreateClientOrdersResponse(Result> result) { + Platform.runLater(() -> { + if (result.getError() != null) { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error creating the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); + return; + } + fallbackManager.setLoading(false); + + isNewOrderMode.set(false); + closeConfirmCreateDialog(); + updateUIOnSuccessfulOperation(); + ToastInfo toastInfo = new ToastInfo("Success", "Client Orders created successfully.", OperationOutcome.SUCCESS); + toastManager.addToast(toastInfo); + }); + return result; + } + + private Result> handleCreateClientOrdersException(Throwable throwable) { + Platform.runLater(() -> { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error creating the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); }); + return new Result<>(); } - private void bindDataToTableView() { - orderIdColumn.setCellValueFactory(new PropertyValueFactory<>("id")); - clientIdColumn.setCellValueFactory(new PropertyValueFactory<>("clientId")); - productIdColumn.setCellValueFactory(new PropertyValueFactory<>("productId")); - quantityColumn.setCellValueFactory(new PropertyValueFactory<>("quantity")); - statusColumn.setCellValueFactory(new PropertyValueFactory<>("status")); - orderDateColumn.setCellValueFactory(new PropertyValueFactory<>("orderDate")); - estimatedDeliveryDateColumn.setCellValueFactory(new PropertyValueFactory<>("estimatedDeliveryDate")); - deliveryDateColumn.setCellValueFactory(new PropertyValueFactory<>("deliveryDate")); + private void handleUpdateOrders(List clientOrders) { + List updateClientOrderDTOs = new ArrayList<>(); + + for (ClientOrder order : clientOrders) { + UpdateClientOrderDTO updateClientOrderDTO = getUpdateClientOrderDTO(order); + + updateClientOrderDTOs.add(updateClientOrderDTO); + } - tableView.getItems().setAll(clientOrders); + fallbackManager.reset(); + fallbackManager.setLoading(true); + + clientOrdersWriteService.updateClientOrdersInBulk(updateClientOrderDTOs) + .thenApply(this::handleUpdateClientOrdersResponse) + .exceptionally(this::handleUpdateClientOrdersException); } - private void setEditEvents() { - clientIdColumn.setOnEditCommit(event -> { - ClientOrder order = event.getRowValue(); - order.setClientId(event.getNewValue()); - updateInDatabase(order); + private UpdateClientOrderDTO getUpdateClientOrderDTO(ClientOrder order) { + UpdateClientOrderDTO updateClientOrderDTO = new UpdateClientOrderDTO(); + updateClientOrderDTO.setId(order.getId()); + updateClientOrderDTO.setOrganizationId(order.getOrganizationId()); + updateClientOrderDTO.setProductId(order.getProduct().getId()); + updateClientOrderDTO.setQuantity(order.getQuantity()); + updateClientOrderDTO.setDeliveredQuantity(order.getDeliveredQuantity()); + updateClientOrderDTO.setOrderDate(order.getOrderDate()); + updateClientOrderDTO.setEstimatedDeliveryDate(order.getEstimatedDeliveryDate()); + updateClientOrderDTO.setDeliveryDate(order.getDeliveryDate()); + updateClientOrderDTO.setStatus(order.getStatus()); + updateClientOrderDTO.setCompanyId(order.getCompanyId()); + + return updateClientOrderDTO; + } + + private Result> handleUpdateClientOrdersResponse(Result> result) { + Platform.runLater(() -> { + if (result.getError() != null) { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error updating the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); + return; + } + fallbackManager.setLoading(false); + + + isNewOrderMode.set(false); + closeConfirmUpdateDialog(); + updateUIOnSuccessfulOperation(); + ToastInfo toastInfo = new ToastInfo("Success", "Client Orders updated successfully.", OperationOutcome.SUCCESS); + toastManager.addToast(toastInfo); }); + return result; + } - productIdColumn.setOnEditCommit(event -> { - ClientOrder order = event.getRowValue(); - order.setProductId(event.getNewValue()); - updateInDatabase(order); + private Result> handleUpdateClientOrdersException(Throwable throwable) { + Platform.runLater(() -> { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error updating the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); }); + return new Result<>(); + } + + private void handleDeleteOrders(List clientOrders) { + List ordersToRemoveIds = new ArrayList<>(); + for (ClientOrder order : clientOrders) { + ordersToRemoveIds.add(order.getId()); + } + + fallbackManager.reset(); + fallbackManager.setLoading(true); + + clientOrdersWriteService.deleteClientOrderInBulk(ordersToRemoveIds) + .thenApply(this::handleDeleteClientOrdersResponse) + .exceptionally(this::handleDeleteClientOrdersException); + } + + private Result> handleDeleteClientOrdersResponse(Result> result) { + Platform.runLater(() -> { + if (result.getError() != null) { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error deleting the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); + return; + } + fallbackManager.setLoading(false); + + tableView.getItems().removeIf(tableData -> result.getData().contains(tableData.getData().getId())); - quantityColumn.setOnEditCommit(event -> { - ClientOrder order = event.getRowValue(); - order.setQuantity(event.getNewValue()); - updateInDatabase(order); + closeConfirmDeleteDialog(); + isEditMode.set(false); + tableView.refresh(); + selectedRowsIndices.clear(); + ToastInfo toastInfo = new ToastInfo("Success", "Client Orders deleted successfully.", OperationOutcome.SUCCESS); + toastManager.addToast(toastInfo); }); + return result; + } - statusColumn.setOnEditCommit(event -> { - ClientOrder order = event.getRowValue(); - order.setStatus(event.getNewValue()); - updateInDatabase(order); + private Result> handleDeleteClientOrdersException(Throwable throwable) { + Platform.runLater(() -> { + ToastInfo toastInfo = new ToastInfo("Error", "There was an error deleting the Client Orders.", OperationOutcome.ERROR); + toastManager.addToast(toastInfo); }); + return new Result<>(); } - private void updateInDatabase(ClientOrder order) { - System.out.println("Change the database with the new value: " + order); + private void updateUIOnSuccessfulOperation() { + isEditMode.set(false); + newOrderCount = 0; + tableView.getSelectionModel().clearSelection(); + tableToolbarController.toggleButtonVisibilityOnCancel(); + + List indicesToClear = new ArrayList<>(selectedRowsIndices); + for (Integer rowIndex : indicesToClear) { + TableData tableRow = tableView.getItems().get(rowIndex); + tableRow.setSelected(false); + } + + selectRowColumn.setEditable(true); + selectedRowsIndices.clear(); + tableView.refresh(); } -} +} \ No newline at end of file diff --git a/src/main/java/org/chainoptim/desktop/features/client/dto/CreateClientOrderDTO.java b/src/main/java/org/chainoptim/desktop/features/client/dto/CreateClientOrderDTO.java index ff6e6a31..6005950e 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/dto/CreateClientOrderDTO.java +++ b/src/main/java/org/chainoptim/desktop/features/client/dto/CreateClientOrderDTO.java @@ -1,16 +1,25 @@ package org.chainoptim.desktop.features.client.dto; +import org.chainoptim.desktop.shared.enums.OrderStatus; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Data +@AllArgsConstructor +@NoArgsConstructor public class CreateClientOrderDTO { + private Integer organizationId; private Integer clientId; private Integer productId; private Float quantity; + private Float deliveredQuantity; private LocalDateTime orderDate; private LocalDateTime estimatedDeliveryDate; private LocalDateTime deliveryDate; + private OrderStatus status; + private String companyId; } diff --git a/src/main/java/org/chainoptim/desktop/features/client/dto/UpdateClientOrderDTO.java b/src/main/java/org/chainoptim/desktop/features/client/dto/UpdateClientOrderDTO.java index 7eaa682d..37a1017f 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/dto/UpdateClientOrderDTO.java +++ b/src/main/java/org/chainoptim/desktop/features/client/dto/UpdateClientOrderDTO.java @@ -1,5 +1,6 @@ package org.chainoptim.desktop.features.client.dto; +import org.chainoptim.desktop.shared.enums.OrderStatus; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -20,4 +21,5 @@ public class UpdateClientOrderDTO { private LocalDateTime orderDate; private LocalDateTime estimatedDeliveryDate; private LocalDateTime deliveryDate; + private OrderStatus status; } diff --git a/src/main/java/org/chainoptim/desktop/features/client/model/ClientOrder.java b/src/main/java/org/chainoptim/desktop/features/client/model/ClientOrder.java index e2fd2b2b..f61b3cfd 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/model/ClientOrder.java +++ b/src/main/java/org/chainoptim/desktop/features/client/model/ClientOrder.java @@ -1,6 +1,8 @@ package org.chainoptim.desktop.features.client.model; +import org.chainoptim.desktop.features.product.model.Product; +import org.chainoptim.desktop.shared.enums.OrderStatus; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -12,15 +14,33 @@ @NoArgsConstructor public class ClientOrder { + public ClientOrder(ClientOrder clientOrder) { + this.id = clientOrder.id; + this.clientId = clientOrder.clientId; + this.createdAt = clientOrder.createdAt; + this.updatedAt = clientOrder.updatedAt; + this.product = clientOrder.product; + this.organizationId = clientOrder.organizationId; + this.quantity = clientOrder.quantity; + this.deliveredQuantity = clientOrder.deliveredQuantity; + this.orderDate = clientOrder.orderDate; + this.estimatedDeliveryDate = clientOrder.estimatedDeliveryDate; + this.deliveryDate = clientOrder.deliveryDate; + this.status = clientOrder.status; + this.companyId = clientOrder.companyId; + } + private Integer id; private Integer clientId; private LocalDateTime createdAt; private LocalDateTime updatedAt; - private Integer productId; + private Product product; private Integer organizationId; private Float quantity; + private Float deliveredQuantity; private LocalDateTime orderDate; private LocalDateTime estimatedDeliveryDate; private LocalDateTime deliveryDate; - private String status; + private OrderStatus status; + private String companyId; } diff --git a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderService.java b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersService.java similarity index 84% rename from src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderService.java rename to src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersService.java index f821fb5a..ac03c888 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderService.java +++ b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersService.java @@ -8,13 +8,12 @@ import java.util.List; import java.util.concurrent.CompletableFuture; -public interface ClientOrderService { +public interface ClientOrdersService { CompletableFuture>> getClientOrdersByOrganizationId(Integer organizationId); CompletableFuture>> getClientOrdersByClientIdAdvanced( Integer clientId, SearchParams searchParams ); - CompletableFuture> getClientOrderById(Integer orderId); } diff --git a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderServiceImpl.java b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersServiceImpl.java similarity index 75% rename from src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderServiceImpl.java rename to src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersServiceImpl.java index e35cbb7b..8fcb7e3c 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderServiceImpl.java +++ b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersServiceImpl.java @@ -2,6 +2,7 @@ import org.chainoptim.desktop.core.user.service.TokenManager; import org.chainoptim.desktop.features.client.model.ClientOrder; +import org.chainoptim.desktop.features.client.service.ClientOrdersService; import org.chainoptim.desktop.shared.caching.CacheKeyBuilder; import org.chainoptim.desktop.shared.caching.CachingService; import org.chainoptim.desktop.shared.httphandling.RequestBuilder; @@ -9,7 +10,6 @@ import org.chainoptim.desktop.shared.httphandling.Result; import org.chainoptim.desktop.shared.search.model.PaginatedResults; import org.chainoptim.desktop.shared.search.model.SearchParams; - import com.fasterxml.jackson.core.type.TypeReference; import com.google.inject.Inject; @@ -18,23 +18,22 @@ import java.util.List; import java.util.concurrent.CompletableFuture; -public class ClientOrderServiceImpl implements ClientOrderService { +public class ClientOrdersServiceImpl implements ClientOrdersService { private final CachingService> cachingService; - private final RequestHandler requestHandler; private final RequestBuilder requestBuilder; + private final RequestHandler requestHandler; private final TokenManager tokenManager; - private static final int STALE_TIME = 300; @Inject - public ClientOrderServiceImpl(CachingService> cachingService, - RequestHandler requestHandler, - RequestBuilder requestBuilder, - TokenManager tokenManager) { + public ClientOrdersServiceImpl(CachingService> cachingService, + RequestBuilder requestBuilder, + RequestHandler requestHandler, + TokenManager tokenManager) { this.cachingService = cachingService; - this.requestHandler = requestHandler; this.requestBuilder = requestBuilder; + this.requestHandler = requestHandler; this.tokenManager = tokenManager; } @@ -42,18 +41,17 @@ public CompletableFuture>> getClientOrdersByOrganizatio String routeAddress = "http://localhost:8080/api/v1/client-orders/organization/" + organizationId.toString(); HttpRequest request = requestBuilder.buildReadRequest(routeAddress, tokenManager.getToken()); - if (request == null) return requestHandler.getParsingErrorResult(); return requestHandler.sendRequest(request, new TypeReference>() {}); } + public CompletableFuture>> getClientOrdersByClientIdAdvanced( Integer clientId, SearchParams searchParams ) { String rootAddress = "http://localhost:8080/api/v1/"; String cacheKey = CacheKeyBuilder.buildAdvancedSearchKey("client-orders", "client", clientId.toString(), searchParams); - String routeAddress = rootAddress + cacheKey; HttpRequest request = requestBuilder.buildReadRequest(routeAddress, tokenManager.getToken()); @@ -68,12 +66,4 @@ public CompletableFuture>> getClientOrdersB }); } - public CompletableFuture> getClientOrderById(Integer orderId) { - String routeAddress = "http://localhost:8080/api/v1/client-orders/" + orderId.toString(); - - HttpRequest request = requestBuilder.buildReadRequest(routeAddress, tokenManager.getToken()); - if (request == null) return requestHandler.getParsingErrorResult(); - - return requestHandler.sendRequest(request, new TypeReference() {}); - } } diff --git a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteService.java b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteService.java similarity index 51% rename from src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteService.java rename to src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteService.java index 32809f51..048ccc0d 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteService.java +++ b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteService.java @@ -5,11 +5,16 @@ import org.chainoptim.desktop.features.client.model.ClientOrder; import org.chainoptim.desktop.shared.httphandling.Result; +import java.util.List; import java.util.concurrent.CompletableFuture; -public interface ClientOrderWriteService { +public interface ClientOrdersWriteService { - CompletableFuture> createClientOrder(CreateClientOrderDTO orderDTO); - CompletableFuture> updateClientOrder(UpdateClientOrderDTO orderDTO); - CompletableFuture> deleteClientOrder(Integer orderId); + CompletableFuture> createClientOrder(CreateClientOrderDTO clientDTO); + + CompletableFuture>> deleteClientOrderInBulk(List orderIds); + + CompletableFuture>> updateClientOrdersInBulk(List orderDTOs); + + CompletableFuture>> createClientOrdersInBulk(List orderDTOs); } diff --git a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceImpl.java b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteServiceImpl.java similarity index 50% rename from src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceImpl.java rename to src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteServiceImpl.java index 4505d8ad..70894417 100644 --- a/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceImpl.java +++ b/src/main/java/org/chainoptim/desktop/features/client/service/ClientOrdersWriteServiceImpl.java @@ -2,32 +2,37 @@ import org.chainoptim.desktop.core.user.service.TokenManager; import org.chainoptim.desktop.features.client.dto.CreateClientOrderDTO; -import org.chainoptim.desktop.features.client.dto.UpdateClientDTO; import org.chainoptim.desktop.features.client.dto.UpdateClientOrderDTO; import org.chainoptim.desktop.features.client.model.ClientOrder; +import org.chainoptim.desktop.features.client.service.ClientOrdersWriteService; +import org.chainoptim.desktop.shared.caching.CachingService; import org.chainoptim.desktop.shared.httphandling.HttpMethod; import org.chainoptim.desktop.shared.httphandling.RequestBuilder; import org.chainoptim.desktop.shared.httphandling.RequestHandler; import org.chainoptim.desktop.shared.httphandling.Result; - +import org.chainoptim.desktop.shared.search.model.PaginatedResults; import com.fasterxml.jackson.core.type.TypeReference; import com.google.inject.Inject; import java.net.http.HttpRequest; +import java.util.List; import java.util.concurrent.CompletableFuture; -public class ClientOrderWriteServiceImpl implements ClientOrderWriteService { +public class ClientOrdersWriteServiceImpl implements ClientOrdersWriteService { - private final RequestHandler requestHandler; + private final CachingService> cachingService; private final RequestBuilder requestBuilder; + private final RequestHandler requestHandler; private final TokenManager tokenManager; @Inject - public ClientOrderWriteServiceImpl(RequestHandler requestHandler, - RequestBuilder requestBuilder, - TokenManager tokenManager) { - this.requestHandler = requestHandler; + public ClientOrdersWriteServiceImpl(CachingService> cachingService, + RequestBuilder requestBuilder, + RequestHandler requestHandler, + TokenManager tokenManager) { + this.cachingService = cachingService; this.requestBuilder = requestBuilder; + this.requestHandler = requestHandler; this.tokenManager = tokenManager; } @@ -36,28 +41,42 @@ public CompletableFuture> createClientOrder(CreateClientOrde HttpRequest request = requestBuilder.buildWriteRequest( HttpMethod.POST, routeAddress, tokenManager.getToken(), orderDTO); - if (request == null) return requestHandler.getParsingErrorResult(); - return requestHandler.sendRequest(request, new TypeReference() {}); + return requestHandler.sendRequest(request, new TypeReference() {}, order -> { + cachingService.clear(); // Invalidate cache + }); + } + + public CompletableFuture>> createClientOrdersInBulk(List orderDTOs) { + String routeAddress = "http://localhost:8080/api/v1/client-orders/create/bulk"; + + HttpRequest request = requestBuilder.buildWriteRequest( + HttpMethod.POST, routeAddress, tokenManager.getToken(), orderDTOs); + + return requestHandler.sendRequest(request, new TypeReference>() {}, orders -> { + cachingService.clear(); // Invalidate cache + }); } - public CompletableFuture> updateClientOrder(UpdateClientOrderDTO orderDTO) { - String routeAddress = "http://localhost:8080/api/v1/client-orders/update"; + public CompletableFuture>> updateClientOrdersInBulk(List orderDTOs) { + String routeAddress = "http://localhost:8080/api/v1/client-orders/update/bulk"; HttpRequest request = requestBuilder.buildWriteRequest( - HttpMethod.PUT, routeAddress, tokenManager.getToken(), orderDTO); - if (request == null) return requestHandler.getParsingErrorResult(); + HttpMethod.PUT, routeAddress, tokenManager.getToken(), orderDTOs); - return requestHandler.sendRequest(request, new TypeReference() {}); + return requestHandler.sendRequest(request, new TypeReference>() {}, orders -> { + cachingService.clear(); // Invalidate cache + }); } - public CompletableFuture> deleteClientOrder(Integer orderId) { - String routeAddress = "http://localhost:8080/api/v1/client-orders/delete/" + orderId; + public CompletableFuture>> deleteClientOrderInBulk(List orderIds) { + String routeAddress = "http://localhost:8080/api/v1/client-orders/delete/bulk"; HttpRequest request = requestBuilder.buildWriteRequest( - HttpMethod.DELETE, routeAddress, tokenManager.getToken(), null); - if (request == null) return requestHandler.getParsingErrorResult(); + HttpMethod.DELETE, routeAddress, tokenManager.getToken(), orderIds); - return requestHandler.sendRequest(request, new TypeReference() {}); + return requestHandler.sendRequest(request, new TypeReference>() {}, ids -> { + cachingService.clear(); // Invalidate cache + }); } } diff --git a/src/main/java/org/chainoptim/desktop/features/product/model/Product.java b/src/main/java/org/chainoptim/desktop/features/product/model/Product.java index 93d5a994..78ec2372 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/model/Product.java +++ b/src/main/java/org/chainoptim/desktop/features/product/model/Product.java @@ -1,6 +1,8 @@ package org.chainoptim.desktop.features.product.model; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import org.chainoptim.desktop.features.productpipeline.model.Stage; import org.chainoptim.desktop.shared.features.location.model.Location; @@ -8,8 +10,21 @@ import java.util.List; @Data +@AllArgsConstructor +@NoArgsConstructor public class Product { + public Product(Product newProduct) { + this.id = newProduct.getId(); + this.name = newProduct.getName(); + this.description = newProduct.getDescription(); + this.createdAt = newProduct.getCreatedAt(); + this.updatedAt = newProduct.getUpdatedAt(); + this.organizationId = newProduct.getOrganizationId(); + this.unit = newProduct.getUnit(); + this.stages = newProduct.getStages(); + } + private Integer id; private String name; private String description; diff --git a/src/main/java/org/chainoptim/desktop/shared/table/util/SelectProductLoader.java b/src/main/java/org/chainoptim/desktop/shared/table/util/SelectProductLoader.java new file mode 100644 index 00000000..7c2adfe3 --- /dev/null +++ b/src/main/java/org/chainoptim/desktop/shared/table/util/SelectProductLoader.java @@ -0,0 +1,70 @@ +package org.chainoptim.desktop.shared.table.util; + +import org.chainoptim.desktop.core.context.TenantContext; +import org.chainoptim.desktop.core.user.model.User; +import org.chainoptim.desktop.features.product.dto.ProductsSearchDTO; +import org.chainoptim.desktop.features.product.service.ProductService; +import org.chainoptim.desktop.shared.httphandling.Result; +import com.google.inject.Inject; +import javafx.application.Platform; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SelectProductLoader { + + + private final ProductService productService; + private final Map productsMap = new HashMap<>(); + + @Inject + public SelectProductLoader(ProductService productService) { + this.productService = productService; + } + + public void initialize() { + loadProducts(); + } + + public List getProductsName() { + return new ArrayList<>(productsMap.values()); + } + + public Integer getProductIdByName(String name) { + for (Map.Entry entry : productsMap.entrySet()) { + if (entry.getValue().equals(name)) { + return entry.getKey(); + } + } + return null; + } + + private void loadProducts() { + User currentUser = TenantContext.getCurrentUser(); + if (currentUser == null) { + return; + } + + Integer organizationId = currentUser.getOrganization().getId(); + productService.getProductsByOrganizationId(organizationId, true) + .thenApply(this::handleProductsResponse) + .exceptionally(this::handleProductsException); + } + + private Result> handleProductsResponse(Result> result) { + Platform.runLater(() -> { + if (result.getError() != null) { + return; + } + productsMap.clear(); + result.getData().forEach(product -> productsMap.put(product.getId(), product.getName())); + }); + return result; + } + + private Result> handleProductsException(Throwable ex) { + return new Result<>(); + } +} diff --git a/src/main/resources/org/chainoptim/desktop/features/client/ClientOrdersView.fxml b/src/main/resources/org/chainoptim/desktop/features/client/ClientOrdersView.fxml index 9a5188f2..ceaae750 100644 --- a/src/main/resources/org/chainoptim/desktop/features/client/ClientOrdersView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/client/ClientOrdersView.fxml @@ -1,27 +1,38 @@ + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceTest.java b/src/test/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceTest.java index b6c02874..1d85acc4 100644 --- a/src/test/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceTest.java +++ b/src/test/java/org/chainoptim/desktop/features/client/service/ClientOrderWriteServiceTest.java @@ -39,7 +39,7 @@ class ClientOrderWriteServiceTest { private TokenManager tokenManager; @InjectMocks - private ClientOrderWriteServiceImpl clientOrderWriteService; + private ClientOrdersWriteServiceImpl clientOrderWriteService; @Test void createClientOrder_Successful() throws Exception { @@ -68,61 +68,61 @@ void createClientOrder_Successful() throws Exception { assertNotNull(resultFuture); assertEquals(HttpURLConnection.HTTP_CREATED, resultFuture.get().getStatusCode()); } - - @Test - void updateClientOrder_Successful() throws Exception { - // Arrange - UpdateClientOrderDTO clientOrderDTO = new UpdateClientOrderDTO(); - String clientOrderDTOString = JsonUtil.getObjectMapper().writeValueAsString(clientOrderDTO); - String fakeToken = "test-token"; - HttpRequest fakeRequest = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/api/v1/client-orders/update")) - .header("Authorization", "Bearer " + fakeToken) - .PUT(HttpRequest.BodyPublishers.ofString(clientOrderDTOString)) - .build(); - ClientOrder expectedClientOrder = new ClientOrder(); - CompletableFuture> expectedFuture = CompletableFuture.completedFuture(new Result<>(expectedClientOrder, null, HttpURLConnection.HTTP_OK)); - - when(requestBuilder.buildWriteRequest(HttpMethod.PUT, "http://localhost:8080/api/v1/client-orders/update", fakeToken, clientOrderDTO)).thenReturn(fakeRequest); - when(requestHandler.sendRequest(eq(fakeRequest), ArgumentMatchers.>any())).thenReturn(expectedFuture); - when(tokenManager.getToken()).thenReturn(fakeToken); - - // Act - CompletableFuture> resultFuture = clientOrderWriteService.updateClientOrder(clientOrderDTO); - - // Assert - verify(requestBuilder).buildWriteRequest(HttpMethod.PUT, "http://localhost:8080/api/v1/client-orders/update", fakeToken, clientOrderDTO); - verify(requestHandler).sendRequest(eq(fakeRequest), ArgumentMatchers.>any()); - assertNotNull(resultFuture); - assertEquals(HttpURLConnection.HTTP_OK, resultFuture.get().getStatusCode()); - } - - @Test - void deleteClientOrder_Successful() throws Exception { - // Arrange - Integer clientOrderId = 1; - String fakeToken = "test-token"; - HttpRequest fakeRequest = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId)) - .header("Authorization", "Bearer " + fakeToken) - .DELETE() - .build(); - Integer expectedResponse = HttpURLConnection.HTTP_OK; // Use an appropriate success code or response - CompletableFuture> expectedFuture = CompletableFuture.completedFuture(new Result<>(expectedResponse, null, HttpURLConnection.HTTP_OK)); - - when(requestBuilder.buildWriteRequest(HttpMethod.DELETE, "http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId, fakeToken, null)).thenReturn(fakeRequest); - when(requestHandler.sendRequest(eq(fakeRequest), ArgumentMatchers.>any())).thenReturn(expectedFuture); - when(tokenManager.getToken()).thenReturn(fakeToken); - - // Act - CompletableFuture> resultFuture = clientOrderWriteService.deleteClientOrder(clientOrderId); - - // Assert - verify(requestBuilder).buildWriteRequest(HttpMethod.DELETE, "http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId, fakeToken, null); - verify(requestHandler).sendRequest(eq(fakeRequest), ArgumentMatchers.>any()); - assertNotNull(resultFuture); - assertEquals(HttpURLConnection.HTTP_OK, resultFuture.get().getStatusCode()); - } +// +// @Test +// void updateClientOrder_Successful() throws Exception { +// // Arrange +// UpdateClientOrderDTO clientOrderDTO = new UpdateClientOrderDTO(); +// String clientOrderDTOString = JsonUtil.getObjectMapper().writeValueAsString(clientOrderDTO); +// String fakeToken = "test-token"; +// HttpRequest fakeRequest = HttpRequest.newBuilder() +// .uri(URI.create("http://localhost:8080/api/v1/client-orders/update")) +// .header("Authorization", "Bearer " + fakeToken) +// .PUT(HttpRequest.BodyPublishers.ofString(clientOrderDTOString)) +// .build(); +// ClientOrder expectedClientOrder = new ClientOrder(); +// CompletableFuture> expectedFuture = CompletableFuture.completedFuture(new Result<>(expectedClientOrder, null, HttpURLConnection.HTTP_OK)); +// +// when(requestBuilder.buildWriteRequest(HttpMethod.PUT, "http://localhost:8080/api/v1/client-orders/update", fakeToken, clientOrderDTO)).thenReturn(fakeRequest); +// when(requestHandler.sendRequest(eq(fakeRequest), ArgumentMatchers.>any())).thenReturn(expectedFuture); +// when(tokenManager.getToken()).thenReturn(fakeToken); +// +// // Act +// CompletableFuture> resultFuture = clientOrderWriteService.updateClientOrder(clientOrderDTO); +// +// // Assert +// verify(requestBuilder).buildWriteRequest(HttpMethod.PUT, "http://localhost:8080/api/v1/client-orders/update", fakeToken, clientOrderDTO); +// verify(requestHandler).sendRequest(eq(fakeRequest), ArgumentMatchers.>any()); +// assertNotNull(resultFuture); +// assertEquals(HttpURLConnection.HTTP_OK, resultFuture.get().getStatusCode()); +// } +// +// @Test +// void deleteClientOrder_Successful() throws Exception { +// // Arrange +// Integer clientOrderId = 1; +// String fakeToken = "test-token"; +// HttpRequest fakeRequest = HttpRequest.newBuilder() +// .uri(URI.create("http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId)) +// .header("Authorization", "Bearer " + fakeToken) +// .DELETE() +// .build(); +// Integer expectedResponse = HttpURLConnection.HTTP_OK; // Use an appropriate success code or response +// CompletableFuture> expectedFuture = CompletableFuture.completedFuture(new Result<>(expectedResponse, null, HttpURLConnection.HTTP_OK)); +// +// when(requestBuilder.buildWriteRequest(HttpMethod.DELETE, "http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId, fakeToken, null)).thenReturn(fakeRequest); +// when(requestHandler.sendRequest(eq(fakeRequest), ArgumentMatchers.>any())).thenReturn(expectedFuture); +// when(tokenManager.getToken()).thenReturn(fakeToken); +// +// // Act +// CompletableFuture> resultFuture = clientOrderWriteService.deleteClientOrder(clientOrderId); +// +// // Assert +// verify(requestBuilder).buildWriteRequest(HttpMethod.DELETE, "http://localhost:8080/api/v1/client-orders/delete/" + clientOrderId, fakeToken, null); +// verify(requestHandler).sendRequest(eq(fakeRequest), ArgumentMatchers.>any()); +// assertNotNull(resultFuture); +// assertEquals(HttpURLConnection.HTTP_OK, resultFuture.get().getStatusCode()); +// } }