/******************************************************************************* * Copyright (c) 2005-2016, MEDEVIT and Elexis * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * <office@medevit.at> - initial implementation * *******************************************************************************/ package ch.elexis.core.ui.views; import java.io.FileWriter; import java.io.IOException; import java.text.MessageFormat; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.FocusCellHighlighter; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TableViewerEditor; import org.eclipse.jface.viewers.TableViewerFocusCellManager; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.ISaveablePart2; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.statushandlers.StatusManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.elexis.core.data.activator.CoreHub; import ch.elexis.core.data.status.ElexisStatus; import ch.elexis.core.lock.types.LockResponse; import ch.elexis.core.model.IStockEntry; import ch.elexis.core.ui.UiDesk; import ch.elexis.core.ui.actions.GlobalActions; import ch.elexis.core.ui.actions.GlobalEventDispatcher; import ch.elexis.core.ui.actions.IActivationListener; import ch.elexis.core.ui.dialogs.OrderImportDialog; import ch.elexis.core.ui.dialogs.StockSelectorDialog; import ch.elexis.core.ui.editors.KontaktSelektorDialogCellEditor; import ch.elexis.core.ui.editors.PersistentObjectEditingSupport; import ch.elexis.core.ui.icons.Images; import ch.elexis.core.ui.util.PersistentObjectDropTarget; import ch.elexis.core.ui.util.SWTHelper; import ch.elexis.core.ui.util.ViewMenus; import ch.elexis.core.ui.util.viewers.CommonViewer; import ch.elexis.core.ui.util.viewers.CommonViewer.Message; import ch.elexis.core.ui.util.viewers.DefaultContentProvider; import ch.elexis.core.ui.util.viewers.ViewerConfigurer; import ch.elexis.core.ui.util.viewers.ViewerConfigurer.WidgetProvider; import ch.elexis.core.ui.views.provider.StockEntryLabelProvider; import ch.elexis.data.Artikel; import ch.elexis.data.Kontakt; import ch.elexis.data.PersistentObject; import ch.elexis.data.Query; import ch.elexis.data.Stock; import ch.elexis.data.StockEntry; import ch.elexis.scripting.CSVWriter; import ch.rgw.tools.ExHandler; public class StockView extends ViewPart implements ISaveablePart2, IActivationListener { public StockView(){} public static final String ID = "ch.elexis.core.ui.views.StockView"; //$NON-NLS-1$ private Logger log = LoggerFactory.getLogger(StockView.class); private CommonViewer cv; private ViewerConfigurer vc; private ViewMenus viewMenus; private IAction refreshAction, exportAction; @Override public void createPartControl(Composite parent){ parent.setLayout(new GridLayout()); cv = new CommonViewer(); vc = new ViewerConfigurer(new DefaultContentProvider(cv, StockEntry.class) { @Override public Object[] getElements(Object inputElement){ return new Query<StockEntry>(StockEntry.class).execute().toArray(); } }, new StockEntryLabelProvider() {}, null, new ViewerConfigurer.DefaultButtonProvider(), new LagerWidgetProvider()); cv.create(vc, parent, SWT.NONE, getViewSite()); cv.getConfigurer().getContentProvider().startListening(); MenuManager contextMenu = new MenuManager(); contextMenu.setRemoveAllWhenShown(true); contextMenu.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager){ manager.add(new CheckInOrderedAction(cv.getViewerWidget())); manager.add(new DeleteStockEntryAction(cv.getViewerWidget())); ArticleMachineOutputAction amoa = new ArticleMachineOutputAction(cv.getViewerWidget()); if (amoa.isVisible()) { manager.add(amoa); manager.add(new FullMachineInventoryAction(cv.getViewerWidget())); } } }); new PersistentObjectDropTarget(cv.getViewerWidget().getControl(), new PersistentObjectDropTarget.IReceiver() { @Override public void dropped(PersistentObject o, DropTargetEvent e){ if (o instanceof Artikel) { Artikel art = (Artikel) o; StockSelectorDialog ssd = new StockSelectorDialog(UiDesk.getTopShell(), false); int open = ssd.open(); if (open == Dialog.OK) { if (ssd.getResult().length > 0) { Stock stock = (Stock) ssd.getResult()[0]; if (stock != null) { CoreHub.getStockService().storeArticleInStock(stock, art.storeToString()); cv.notify(Message.update); } } } } } @Override public boolean accept(PersistentObject o){ if (o instanceof Artikel) { Artikel art = (Artikel) o; return !art.isProduct(); } return false; } }); cv.setContextMenu(contextMenu); makeActions(); viewMenus = new ViewMenus(getViewSite()); viewMenus.createToolbar(refreshAction); viewMenus.createMenu(exportAction); GlobalEventDispatcher.addActivationListener(this, this); } private void makeActions(){ refreshAction = new Action(Messages.StockView_reload) { { setImageDescriptor(Images.IMG_REFRESH.getImageDescriptor()); } @Override public void run(){ cv.notify(Message.update); } }; exportAction = new Action(Messages.LagerView_exportAction, Images.IMG_EXPORT.getImageDescriptor()) { @Override public void run(){ FileDialog dialog = new FileDialog(UiDesk.getTopShell(), SWT.SAVE); dialog.setFilterExtensions(new String[] { "*.csv" }); dialog.setFilterNames(new String[] { "Comma Separated Values (CSV)" }); dialog.setOverwrite(true); dialog.setFileName("lager_export.csv"); String pathToSave = dialog.open(); if (pathToSave != null) { CSVWriter csv = null; try { int errorUnkownArticle = 0; int success = 0; csv = new CSVWriter(new FileWriter(pathToSave)); log.debug("csv export started for: " + pathToSave); String[] header = new String[] { "Name", "Pharmacode", "EAN", "Max", "Min", "Aktuell Packung an Lager", "Aktuell an Lager (Anbruch)", " Stück pro Packung", "Stück pro Abgabe", "Einkaufspreis", "Verkaufspreis", "Typ nach Liste (SL, SL-Betäubung, P, N, LPPV, Migl)", "Lieferant" }; csv.writeNext(header); for (Object o : vc.getContentProvider().getElements(null)) { if (o instanceof StockEntry) { String[] line = new String[header.length]; StockEntry stockEntry = (StockEntry) o; Artikel artikel = stockEntry.getArticle(); if (artikel != null) { line[0] = artikel.getLabel(); line[1] = artikel.getPharmaCode(); line[2] = artikel.getEAN(); line[3] = String.valueOf(stockEntry.getMaximumStock()); line[4] = String.valueOf(stockEntry.getMinimumStock()); line[5] = String.valueOf(stockEntry.getCurrentStock()); line[6] = String.valueOf(stockEntry.getFractionUnits()); line[7] = String.valueOf(artikel.getPackungsGroesse()); line[8] = String.valueOf(artikel.getAbgabeEinheit()); line[9] = artikel.getEKPreis().getAmountAsString(); line[10] = artikel.getVKPreis().getAmountAsString(); line[11] = artikel.get(Artikel.FLD_TYP); Kontakt provider = stockEntry.getProvider(); if (provider != null) { line[12] = provider.getLabel(); } csv.writeNext(line); success++; } else { errorUnkownArticle++; log.warn("cannot export: id [" + stockEntry.getId() + "] artikelId [" + stockEntry.get(StockEntry.FLD_ARTICLE_ID) + "] artikelType [" + stockEntry.get(StockEntry.FLD_ARTICLE_TYPE) + "] "); } } } csv.close(); log.debug("csv export finished for: " + pathToSave); StringBuffer msg = new StringBuffer(); msg.append("Der Export nach "); msg.append(pathToSave); msg.append(" ist abgeschlossen."); msg.append("\n\n"); msg.append(success); msg.append(" Artikel wurden erfolgreich exportiert."); if (errorUnkownArticle > 0) { msg.append("\n"); msg.append(errorUnkownArticle); msg.append( " Artikel konnten nicht exportiert werden (Unbekannte Artikel Typen)."); } SWTHelper.showInfo("Lager export", msg.toString()); } catch (Exception ex) { ExHandler.handle(ex); log.error("csv exporter error", ex); SWTHelper.showError("Fehler", ex.getMessage()); } finally { if (csv != null) { try { csv.close(); } catch (IOException e) { log.error("cannot close csv exporter", e); } } } } } }; } @Override public void setFocus(){ // cv.getConfigurer().getControlFieldProvider().setFocus(); } @Override public void dispose(){ cv.getConfigurer().getContentProvider().stopListening(); GlobalEventDispatcher.removeActivationListener(this, this); super.dispose(); } class LagerWidgetProvider implements WidgetProvider { String[] columns = { Messages.LagerView_stock, Messages.LagerView_pharmacode, Messages.LagerView_gtin, Messages.LagerView_name, Messages.LagerView_minBestand, Messages.LagerView_istBestand, Messages.LagerView_maxBestand, Messages.LagerView_dealer }; int[] colwidth = { 40, 75, 90, 250, 35, 35, 35, 150 }; public StructuredViewer createViewer(Composite parent){ Table table = new Table(parent, SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.SINGLE | SWT.VIRTUAL); table.setHeaderVisible(true); table.setLinesVisible(false); TableViewer ret = new TableViewer(table); for (int i = 0; i < columns.length; i++) { TableViewerColumn tvc = new TableViewerColumn(ret, SWT.NONE); TableColumn tc = tvc.getColumn(); tc.setText(columns[i]); tc.setWidth(colwidth[i]); tc.setData(i); tc.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e){ cv.getViewerWidget().setSorter(new LagerTableSorter( (Integer) ((TableColumn) e.getSource()).getData())); } }); PersistentObjectEditingSupport poes = null; if (i == 4) { poes = new PersistentObjectEditingSupport(ret, StockEntry.FLD_MIN, Integer.class, true); } else if (i == 5) { poes = new PersistentObjectEditingSupport(ret, StockEntry.FLD_CURRENT, Integer.class, true) { protected boolean canEdit(Object element){ boolean canEdit = super.canEdit(element); if (canEdit) { StockEntry se = (StockEntry) element; return !se.getStock().isCommissioningSystem(); } return true; }; }; } else if (i == 6) { poes = new PersistentObjectEditingSupport(ret, StockEntry.FLD_MAX, Integer.class, true); } if (poes != null) { tvc.setEditingSupport(poes); } if (i == 7) { EditingSupport providerEditingSupport = new EditingSupport(ret) { @Override protected void setValue(Object element, Object value){ StockEntry se = (StockEntry) element; if (se == null) { return; } LockResponse lr = CoreHub.getLocalLockService().acquireLock(se); if (!lr.isOk()) { return; } se.setProvider((Kontakt) value); lr = CoreHub.getLocalLockService().releaseLock((se)); if (!lr.isOk()) { log.warn("Error releasing lock for [{}]: {}", se.getId(), lr.getStatus()); } getViewer().refresh(); } @Override protected Object getValue(Object element){ IStockEntry se = (IStockEntry) element; if (se == null) { return null; } return (Kontakt) se.getProvider(); } @Override protected CellEditor getCellEditor(Object element){ return new KontaktSelektorDialogCellEditor( ((TableViewer) getViewer()).getTable(), "Lieferant auswählen", "Bitte selektieren Sie den Lieferant"); } @Override protected boolean canEdit(Object element){ StockEntry stockEntry = (StockEntry) element; return (stockEntry != null && stockEntry.getArticle() != null); } }; tvc.setEditingSupport(providerEditingSupport); } } ret.setSorter(new LagerTableSorter(3)); TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(ret, new FocusCellHighlighter(ret) {}); ColumnViewerEditorActivationStrategy editorActivationStrategy = new ColumnViewerEditorActivationStrategy(ret) { @Override protected boolean isEditorActivationEvent( ColumnViewerEditorActivationEvent event) { ViewerCell cell = (ViewerCell) event.getSource(); return cell.getColumnIndex() > 3 && cell.getColumnIndex() < 7; } }; TableViewerEditor.create(ret, focusCellManager, editorActivationStrategy, TableViewerEditor.TABBING_HORIZONTAL); return ret; } class LagerTableSorter extends ViewerSorter { int col; LagerTableSorter(int c){ col = c; } @Override public int compare(Viewer viewer, Object e1, Object e2){ String s1 = ((StockEntryLabelProvider) cv.getConfigurer().getLabelProvider()) .getColumnText(e1, col).toLowerCase(); String s2 = ((StockEntryLabelProvider) cv.getConfigurer().getLabelProvider()) .getColumnText(e2, col).toLowerCase(); return s1.compareTo(s2); } } } public class FullMachineInventoryAction extends Action { private Viewer viewer; public FullMachineInventoryAction(Viewer viewer){ this.viewer = viewer; } @Override public ImageDescriptor getImageDescriptor(){ return Images.IMG_SYNC.getImageDescriptor(); } @Override public String getText(){ return Messages.StockView_PerformFullInventoryOnCommSystem; } public void run(){ StockEntry stockEntry = fetchSelection(); IStatus status = CoreHub.getStockCommissioningSystemService() .synchronizeInventory(stockEntry.getStock(), null, null); if(!status.isOK()) { ElexisStatus elStatus = new ElexisStatus(status); StatusManager.getManager().handle(elStatus, StatusManager.SHOW); } } private StockEntry fetchSelection(){ IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (selection != null && !selection.isEmpty() && selection.getFirstElement() instanceof StockEntry) { return (StockEntry) selection.getFirstElement(); } return null; }; } public class ArticleMachineOutputAction extends Action { private Viewer viewer; public ArticleMachineOutputAction(Viewer viewer){ this.viewer = viewer; } public boolean isVisible(){ StockEntry stockEntry = fetchSelection(); if (stockEntry != null) { Stock stock = stockEntry.getStock(); if (stock != null) { String driverUuid = stock.getDriverUuid(); return (driverUuid != null && driverUuid.length() > 8); } } return false; } @Override public String getText(){ return Messages.StockView_OutlayArticle; } public void run(){ StockEntry stockEntry = fetchSelection(); IStatus status = CoreHub.getStockCommissioningSystemService() .performArticleOutlay(stockEntry, 1, null); if(!status.isOK()) { ElexisStatus elStatus = new ElexisStatus(status); StatusManager.getManager().handle(elStatus, StatusManager.SHOW); } } private StockEntry fetchSelection(){ IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (selection != null && !selection.isEmpty() && selection.getFirstElement() instanceof StockEntry) { return (StockEntry) selection.getFirstElement(); } return null; }; } public class CheckInOrderedAction extends Action { private Viewer viewer; private StockEntry stockEntry; public CheckInOrderedAction(Viewer viewer){ this.viewer = viewer; } @Override public boolean isEnabled(){ stockEntry = null; IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (selection != null && !selection.isEmpty() && selection.getFirstElement() instanceof StockEntry) { stockEntry = (StockEntry) selection.getFirstElement(); if (stockEntry.getArticle() != null) { return (CoreHub.getOrderService() .findOpenOrderEntryForStockEntry(stockEntry) != null); } } return false; } @Override public String getText(){ return Messages.BestellView_CheckInCaption; } @Override public void run(){ OrderImportDialog dialog = new OrderImportDialog(viewer.getControl().getShell(), stockEntry); dialog.open(); viewer.refresh(); } } public class DeleteStockEntryAction extends Action { private Viewer viewer; private StockEntry stockEntry; public DeleteStockEntryAction(Viewer viewer){ this.viewer = viewer; } @Override public boolean isEnabled(){ stockEntry = null; IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (selection != null && !selection.isEmpty() && selection.getFirstElement() instanceof StockEntry) { stockEntry = (StockEntry) selection.getFirstElement(); if (stockEntry != null) { Stock stock = stockEntry.getStock(); return stock != null && !stock.isCommissioningSystem(); } } return false; } @Override public String getText(){ return Messages.LagerView_deleteAction; } @Override public String getToolTipText() { return Messages.LagerView_deleteActionToolTip; } @Override public void run(){ if (stockEntry != null) { Artikel article = stockEntry.getArticle(); if (article != null && MessageDialog.openConfirm( viewer.getControl().getShell(), Messages.LagerView_deleteActionConfirmCaption, MessageFormat.format(Messages.LagerView_deleteConfirmBody, article.getName()))) { stockEntry.delete(); viewer.refresh(); } } } } /*********************************************************************************************** * Die folgenden 6 Methoden implementieren das Interface ISaveablePart2 Wir benötigen das * Interface nur, um das Schliessen einer View zu verhindern, wenn die Perspektive fixiert ist. * Gibt es da keine einfachere Methode? */ public int promptToSaveOnClose(){ return GlobalActions.fixLayoutAction.isChecked() ? ISaveablePart2.CANCEL : ISaveablePart2.NO; } public void doSave(IProgressMonitor monitor){ /* leer */ } public void doSaveAs(){ /* leer */ } public boolean isDirty(){ return true; } public boolean isSaveAsAllowed(){ return false; } public boolean isSaveOnCloseNeeded(){ return true; } public void activation(boolean mode){} public void visible(boolean mode){ if (mode) { cv.notify(CommonViewer.Message.update); } } }