/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.receipt;
import eu.ggnet.dwoss.stock.entity.Shipment;
import eu.ggnet.dwoss.stock.entity.StockUnit;
import eu.ggnet.dwoss.stock.entity.StockTransaction;
import eu.ggnet.dwoss.stock.entity.Stock;
import java.awt.Component;
import java.awt.Window;
import java.util.Objects;
import javax.swing.*;
import org.apache.commons.lang3.StringUtils;
import eu.ggnet.saft.core.Workspace;
import eu.ggnet.saft.core.authorisation.Guardian;
import eu.ggnet.dwoss.receipt.product.ComboBoxDialog;
import eu.ggnet.dwoss.receipt.unit.*;
import eu.ggnet.dwoss.rules.ReceiptOperation;
import eu.ggnet.dwoss.stock.StockAgent;
import eu.ggnet.dwoss.uniqueunit.entity.UniqueUnit;
import eu.ggnet.dwoss.util.UserInfoException;
import lombok.Value;
import static eu.ggnet.saft.core.Client.lookup;
/**
* Ui support for the unit Operations.
* <p/>
* @author oliver.guenther
*/
public class UiUnitSupport {
@Value
private final static class UnitAndModel {
private final UnitModel unitModel;
private final UniqueUnit uniqueUnit;
}
public class StockCellRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if ( value == null ) return label;
if ( value instanceof Stock ) label.setText(((Stock)value).getName());
return label;
}
}
private final UnitProcessor unitProcessor;
public UiUnitSupport(UnitProcessor unitProcessor) {
this.unitProcessor = Objects.requireNonNull(unitProcessor, UnitProcessor.class.getSimpleName() + " must not be null");
}
/**
* Starts the Ui to create a new Unit in the stock.
* <p/>
* @param stockTransaction the stockTransaction, that will be used to rollin the unit.
* @param productShipment the productShipment the unit is comming from.
* @param parent the parent window to center the dialog
*/
public void createUnit(StockTransaction stockTransaction, Shipment productShipment, Window parent) {
UnitAndModel result = createEditUnit(parent, null, null, null, productShipment);
if ( result == null ) return;
unitProcessor.receipt(
result.getUniqueUnit(),
result.getUnitModel().getProduct(),
productShipment,
stockTransaction,
result.getUnitModel().getOperation(),
result.getUnitModel().getOperationComment(),
lookup(Guardian.class).getUsername()
);
}
/**
* Starts the Ui to edit an existing Unit.
* <p/>
* @param refurbishedIdOrSerial the refurbishId or a serial
* @throws UserInfoException if the unit may not be edited.
*/
public void editUnit(String refurbishedIdOrSerial) throws UserInfoException {
Window parent = lookup(Workspace.class).getMainFrame();
if ( refurbishedIdOrSerial == null || refurbishedIdOrSerial.trim().equals("") ) return;
refurbishedIdOrSerial = refurbishedIdOrSerial.trim().toUpperCase();
UnitProcessor.EditableUnit eu = unitProcessor.findEditableUnit(refurbishedIdOrSerial);
if ( eu.getOperation() == ReceiptOperation.IN_SALE ) {
JOptionPane.showMessageDialog(parent, "Achtung, dieses Gerät ist in einem Kundenauftrag, ändern nicht empfohlen.");
} else if ( eu.getOperation() != ReceiptOperation.SALEABLE ) {
JOptionPane.showMessageDialog(parent, "Gerät ist in Operation : " + eu.getOperation());
}
UniqueUnit uu = eu.getUniqueUnit();
if ( eu.getStockUnit() != null )
uu = optionalChangeStock(eu.getUniqueUnit(), eu.getStockUnit(), lookup(Workspace.class).getValue(Stock.class), parent, lookup(Guardian.class).getUsername());
UnitAndModel result = createEditUnit(parent, uu, eu.getOperation(), eu.getPartNo(), null);
if ( result == null ) return;
unitProcessor.update(
result.getUniqueUnit(),
result.getUnitModel().getProduct(),
result.getUnitModel().getOperation(),
result.getUnitModel().getOperationComment(),
lookup(Guardian.class).getUsername()
);
}
/**
* Part of create and Edit, which is equal.
* <p/>
* @param parent the parent for layout
* @param inUnit the unit to manipulate. (Only needed in Edit)
* @param receiptOperation the last receiptOperation (Only needed in Edit)
* @param partNo the partNo of the unit.product (Only needed in Edit and if the UniqueUnit.product == null)
* @param shipment the shipment (Only needed in Create)
* @return a tuple of the modified unit and the ui model for supplementary information or null if the manipulation has been canceled.
*/
private UnitAndModel createEditUnit(final Window parent,
final UniqueUnit inUnit,
final ReceiptOperation receiptOperation,
final String partNo,
final Shipment shipment) {
UnitModel model = new UnitModel();
if ( inUnit != null ) model.setContractor(inUnit.getContractor()); // Only on Edit
if ( receiptOperation != null ) model.setOperation(receiptOperation); // Only on Edit
UnitController controller = new UnitController();
controller.setModel(model);
UnitView view = new UnitView(parent);
view.setModel(model);
view.setController(controller);
controller.setView(view);
if ( shipment != null ) view.setShipment(shipment); // Only on Create
if ( inUnit != null ) { // Only on Edit
view.setUnit(inUnit);
if ( inUnit.getProduct() == null ) view.setPartNo(partNo); // Extra on Edit
}
controller.init();
view.setVisible(true);
if ( view.isCancel() ) return null; // HINT JDK8 OptionalPattern
// This would normaly be in the controller, but the design of the UnitView Controller is a little bit stupid
UniqueUnit uniqueUnit = view.getUnit();
if ( !StringUtils.isBlank(model.getOperationComment()) ) {
uniqueUnit.setInternalComment(uniqueUnit.getInternalComment() + ", " + model.getOperation() + ":" + model.getOperationComment());
}
return new UnitAndModel(model, uniqueUnit);
}
private UniqueUnit optionalChangeStock(UniqueUnit uniqueUnit, StockUnit stockUnit, Stock localStock, Window parent, String account) {
if ( !stockUnit.isInStock() ) return uniqueUnit;
if ( localStock.equals(stockUnit.getStock()) ) return uniqueUnit;
if ( stockUnit.isInTransaction() ) {
JOptionPane.showMessageDialog(parent,
"Achtung, Gerät ist nicht auf " + localStock.getName() + ",\n"
+ "aber Gerät ist auch auf einer Transaktion.\n"
+ "Automatische Lageränderung nicht möglich !");
return uniqueUnit;
}
int option = JOptionPane.showConfirmDialog(parent,
"Gerät steht nicht auf " + localStock.getName() + ", welches als Standort angegeben ist. Gerätestandort ändern ?",
"Standortabweichung", JOptionPane.YES_NO_OPTION);
if ( option == JOptionPane.YES_OPTION ) {
ComboBoxDialog<Stock> dialog = new ComboBoxDialog<>(parent, lookup(StockAgent.class).findAll(Stock.class).toArray(new Stock[0]), new StockCellRenderer());
dialog.setSelection(localStock);
dialog.setVisible(true);
if ( dialog.isOk() ) return unitProcessor.transfer(uniqueUnit, dialog.getSelection().getId(), account);
}
return uniqueUnit;
}
}