/*******************************************************************************
* Copyright (c) 2005-2010, G. Weirich 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:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.elexis.core.ui.views.rechnung;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;
import ch.elexis.admin.AccessControlDefaults;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.ui.util.Log;
import ch.elexis.core.ui.util.viewers.CommonViewer;
import ch.elexis.core.ui.util.viewers.ViewerConfigurer;
import ch.elexis.core.ui.util.viewers.ViewerConfigurer.ControlFieldListener;
import ch.elexis.data.Fall;
import ch.elexis.data.Konsultation;
import ch.elexis.data.Patient;
import ch.elexis.data.Query;
import ch.elexis.data.Rechnung;
import ch.elexis.data.RnStatus;
import ch.elexis.data.Zahlung;
import ch.rgw.tools.ExHandler;
import ch.rgw.tools.IFilter;
import ch.rgw.tools.Money;
import ch.rgw.tools.TimeTool;
import ch.rgw.tools.Tree;
/**
* Contentprovider used in "RechnungsListeView" to display bills selected by some criteria
*
* @author gerry
*
*/
class RnContentProvider implements ViewerConfigurer.ICommonViewerContentProvider,
ITreeContentProvider, ControlFieldListener {
private static final float PREVAL = 50000f;
// private Query<Rechnung> q1;
CommonViewer cv;
Tree[] result;
int iPat, iRn;
Money mAmount, mOpen;
TreeComparator treeComparator = new TreeComparator();
PatientComparator patientComparator = new PatientComparator();
RechnungsListeView rlv;
String[] constraints;
String[] val;
private final Log log = Log.get("Rechnungenlader"); //$NON-NLS-1$
RnContentProvider(final RechnungsListeView l, final CommonViewer cv){
this.cv = cv;
rlv = l;
}
public void startListening(){
cv.getConfigurer().getControlFieldProvider().addChangeListener(this);
}
public void stopListening(){
cv.getConfigurer().getControlFieldProvider().removeChangeListener(this);
}
@SuppressWarnings("unchecked")
public Object[] getElements(final Object inputElement){
IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
try {
progressService.run(true, true, new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor){
reload(monitor);
if (monitor.isCanceled()) {
monitor.done();
}
rlv.getSite().getShell().getDisplay().syncExec(new Runnable() {
@Override
public void run(){
if (rlv.tPat != null) {
rlv.tPat.setText(Integer.toString(iPat));
rlv.tRn.setText(Integer.toString(iRn));
rlv.tSum.setText(mAmount.getAmountAsString());
rlv.tOpen.setText(mOpen.getAmountAsString());
}
}
});
}
});
} catch (Throwable ex) {
ExHandler.handle(ex);
}
return result == null ? new Tree[0] : result;
}
public void dispose(){
// TODO Automatisch erstellter Methoden-Stub
}
public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput){
// TODO Automatisch erstellter Methoden-Stub
}
// Vom ControlFieldListener
public void changed(HashMap<String, String> values){
cv.notify(CommonViewer.Message.update);
}
public void reorder(final String field){
cv.getViewerWidget().setSorter(new ViewerSorter() {
@Override
public int compare(final Viewer viewer, final Object e1, final Object e2){
TimeTool t1 = getLatest((Tree) e1);
TimeTool t2 = getLatest((Tree) e2);
return t1.compareTo(t2);
}
});
}
public void selected(){
// nothing to do
}
@SuppressWarnings("unchecked")
private TimeTool getLatest(final Tree t){
if (t.contents instanceof Rechnung) {
return new TimeTool(((Rechnung) t.contents).getDatumRn());
} else if (t.contents instanceof Fall) {
return getLatestFromCase(t);
} else if (t.contents instanceof Patient) {
Tree runner = t.getFirstChild();
TimeTool latest = new TimeTool();
while (runner != null) {
TimeTool lff = getLatestFromCase(runner);
if (lff.isBefore(latest)) {
latest.set(lff);
}
runner = runner.getNextSibling();
}
return latest;
}
return null;
}
@SuppressWarnings("unchecked")
private TimeTool getLatestFromCase(final Tree c){
List<Tree> tRn = (List<Tree>) c.getChildren();
TimeTool tL = new TimeTool();
for (Tree t : tRn) {
Rechnung rn = (Rechnung) t.contents;
TimeTool ttR = new TimeTool(rn.getDatumRn());
if (ttR.isBefore(tL)) {
tL.set(ttR);
}
}
return tL;
}
@SuppressWarnings("unchecked")
public Object[] getChildren(final Object parentElement){
if (parentElement instanceof Tree) {
Tree[] ret = (Tree[]) ((Tree) parentElement).getChildren().toArray(new Tree[0]);
Arrays.sort(ret, treeComparator);
return ret;
}
return new Object[0];
}
@SuppressWarnings("unchecked")
public Object getParent(final Object element){
if (element instanceof Tree) {
return ((Tree) element).getParent();
}
return null;
}
public boolean hasChildren(final Object element){
if (element instanceof Tree) {
if (((Tree) element).contents instanceof Rechnung) {
return false;
}
}
return true;
}
public void setConstraints(final String[] constraints){
this.constraints = constraints;
}
public Query<Rechnung> prepareQuery(){
cv.getParent().getDisplay().syncExec(new Runnable() {
@Override
public void run(){
val = null;
val = cv.getConfigurer().getControlFieldProvider().getValues();
}
});
Query<Rechnung> q1 = new Query<Rechnung>(Rechnung.class);
if (CoreHub.acl.request(AccessControlDefaults.ACCOUNTING_GLOBAL) == false) {
if (CoreHub.actMandant == null) {
return null;
}
q1.add(Rechnung.MANDATOR_ID, Query.EQUALS, CoreHub.actMandant.getId());
}
if (val[2] != null) {
q1.add(Rechnung.BILL_NUMBER, Query.EQUALS, val[2]);
} else if (val[3] != null) {
q1.add(Rechnung.BILL_AMOUNT_CENTS, Query.EQUALS, val[3]);
} else {
if (Integer.parseInt(val[0]) == RnStatus.ZU_DRUCKEN) {
q1.startGroup();
q1.add(Rechnung.BILL_STATE, Query.EQUALS, Integer.toString(RnStatus.OFFEN));
q1.or();
q1.add(Rechnung.BILL_STATE, Query.EQUALS, Integer.toString(RnStatus.MAHNUNG_1));
q1.add(Rechnung.BILL_STATE, Query.EQUALS, Integer.toString(RnStatus.MAHNUNG_2));
q1.add(Rechnung.BILL_STATE, Query.EQUALS, Integer.toString(RnStatus.MAHNUNG_3));
q1.endGroup();
q1.and();
} else if (Integer.parseInt(val[0]) == RnStatus.AUSSTEHEND) {
q1.startGroup();
q1.add(Rechnung.BILL_STATE, Query.EQUALS,
Integer.toString(RnStatus.OFFEN_UND_GEDRUCKT));
q1.or();
q1.add(Rechnung.BILL_STATE, Query.EQUALS,
Integer.toString(RnStatus.MAHNUNG_1_GEDRUCKT));
q1.add(Rechnung.BILL_STATE, Query.EQUALS,
Integer.toString(RnStatus.MAHNUNG_2_GEDRUCKT));
q1.add(Rechnung.BILL_STATE, Query.EQUALS,
Integer.toString(RnStatus.MAHNUNG_3_GEDRUCKT));
q1.endGroup();
q1.and();
} else if (!val[0].equals(StringConstants.ZERO)) {
q1.add(Rechnung.BILL_STATE, Query.EQUALS, val[0]);
}
if (val[1] != null) {
Patient act = Patient.load(val[1]);
if (act.exists()) {
Fall[] faelle = act.getFaelle();
if ((faelle != null) && (faelle.length > 0)) {
q1.startGroup();
q1.insertFalse();
q1.or();
for (Fall fall : faelle) {
// if (fall.isOpen()) {
q1.add(Rechnung.CASE_ID, Query.EQUALS, fall.getId());
// }
}
q1.endGroup();
}
}
}
if (constraints != null) {
for (String line : constraints) {
q1.addToken(line);
}
}
}
if (val[4] != null) {
q1.addPostQueryFilter(new IFilter() {
public boolean select(Object toTest){
if (toTest instanceof Rechnung) {
Rechnung rn = (Rechnung) toTest;
Fall fall = rn.getFall();
if (fall != null) {
String abr = fall.getAbrechnungsSystem();
if (abr != null) {
if (abr.equals(val[4])) {
return true;
}
}
}
}
return false;
}
});
}
return q1;
}
@SuppressWarnings("unchecked")
public void reload(final IProgressMonitor monitor){
monitor.beginTask(Messages.RnContentProvider_collectInvoices, Math.round(PREVAL)); //$NON-NLS-1$
monitor.subTask(Messages.RnContentProvider_prepare); //$NON-NLS-1$
Tree<Patient> root = new Tree<Patient>(null, null);
Hashtable<String, Tree<Patient>> hPats = new Hashtable<String, Tree<Patient>>(367, 0.75f);
Hashtable<String, Tree<Fall>> hFaelle = new Hashtable<String, Tree<Fall>>(719, 0.75f);
Query<Rechnung> q1 = prepareQuery();
if (q1 == null) {
return;
}
q1.orderBy(false, Rechnung.BILL_DATE);
List<Rechnung> rechnungen = q1.execute();
if (rechnungen == null) {
log.log(Messages.RnContentProvider_errorRetriveingBillds, Log.ERRORS); //$NON-NLS-1$
return;
}
monitor.worked(100);
monitor.subTask(Messages.RnContentProvider_databseRequest); //$NON-NLS-1$
int multiplyer = Math.round(PREVAL / rechnungen.size());
monitor.subTask(Messages.RnContentProvider_load); //$NON-NLS-1$
iPat = 0;
iRn = rechnungen.size();
mAmount = new Money();
mOpen = new Money();
for (Rechnung rn : rechnungen) {
if (monitor.isCanceled()) {
monitor.worked(1);
monitor.done();
return;
}
if ((rn == null) || (!rn.exists())) {
log.log("Fehlerhafte Rechnung", Log.ERRORS); //$NON-NLS-1$
continue;
}
mAmount.addMoney(rn.getOffenerBetrag());
mOpen.addMoney(sumZahlungen(rn));
Fall fall = rn.getFall();
if (fall == null) {
log.log("Rechnung " + rn.getId() + " hat keinen Fall", Log.WARNINGS); //$NON-NLS-1$ //$NON-NLS-2$
continue;
}
Tree<Fall> tFall = hFaelle.get(fall.getId());
if (tFall == null) {
Patient pat = fall.getPatient();
if (pat == null) {
log.log("Fall " + fall.getId() + " hat keinen Patienten", Log.WARNINGS); //$NON-NLS-1$ //$NON-NLS-2$
continue;
}
Tree<Patient> tPat = hPats.get(pat.getId());
if (tPat == null) {
tPat = new Tree<Patient>(root, pat, patientComparator);
hPats.put(pat.getId(), tPat);
iPat++;
}
tFall = new Tree(tPat, fall);
hFaelle.put(fall.getId(), tFall);
}
Tree<Rechnung> tRn = new Tree(tFall, rn);
monitor.worked(multiplyer);
}
monitor.worked(1);
monitor.subTask(Messages.RnContentProvider_prepareSort); //$NON-NLS-1$
result = root.getChildren().toArray(new Tree[0]);
monitor.worked(100);
//monitor.subTask(Messages.getString("RnContentProvider.sort")); //$NON-NLS-1$
// Arrays.sort(result,treeComparator);
monitor.done();
}
/**
* Bereits bezahlten Betrag holen. Alle Zahlungen ausser Storno werden addiert.
*/
public Money sumZahlungen(Rechnung rn){
List<Zahlung> lz = rn.getZahlungen();
Money total = new Money();
for (Zahlung z : lz) {
Money abzahlung = z.getBetrag();
if (!z.getBemerkung().equalsIgnoreCase("storno")) {
total.addMoney(abzahlung);
}
}
return total;
}
private static class PatientComparator implements Comparator {
public int compare(final Object o1, final Object o2){
Patient p1 = (Patient) o1;
Patient p2 = (Patient) o2;
return p1.getLabel().compareTo(p2.getLabel());
}
}
private static class TreeComparator implements Comparator {
TimeTool tt0 = new TimeTool();
TimeTool tt1 = new TimeTool();
public int compare(final Object arg0, final Object arg1){
Tree t0 = (Tree) arg0;
Tree t1 = (Tree) arg1;
if (t0.contents instanceof Patient) {
Patient p0 = (Patient) t0.contents;
Patient p1 = (Patient) t1.contents;
String s0 = p0.getLabel();
String s1 = p1.getLabel();
return s0.compareTo(s1);
} else if (t0.contents instanceof Fall) {
Fall f0 = (Fall) t0.contents;
Fall f1 = (Fall) t1.contents;
tt0.set(f0.getBeginnDatum());
tt1.set(f1.getBeginnDatum());
return tt0.secondsTo(tt1);
} else if (t0.contents instanceof Konsultation) {
Konsultation b0 = (Konsultation) t0.contents;
Konsultation b1 = (Konsultation) t1.contents;
tt0.set(b0.getDatum());
tt1.set(b1.getDatum());
return tt0.secondsTo(tt1);
} else {
return 0;
}
}
}
@Override
public void init(){
// TODO Auto-generated method stub
}
}