456 lines
17 KiB
Java
456 lines
17 KiB
Java
package com.alexanderlogistics;
|
|
|
|
import java.io.Serializable;
|
|
import java.time.LocalDate;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.logging.Logger;
|
|
|
|
import org.imixs.workflow.ItemCollection;
|
|
import org.imixs.workflow.WorkflowKernel;
|
|
import org.imixs.workflow.engine.DocumentService;
|
|
import org.imixs.workflow.engine.WorkflowService;
|
|
import org.imixs.workflow.exceptions.PluginException;
|
|
import org.imixs.workflow.faces.data.WorkflowController;
|
|
import org.imixs.workflow.faces.data.WorkflowEvent;
|
|
|
|
import jakarta.enterprise.context.ConversationScoped;
|
|
import jakarta.enterprise.event.Observes;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.inject.Named;
|
|
|
|
/**
|
|
* Der OPListeController dient dazu eine liste aller offenen Ausgangsrechnungen
|
|
* zu bilden
|
|
* <p>
|
|
* Zusätzlich bietet er die funktionen zum auszifferne. Dies bedeutet, der
|
|
* controller ermittelt zunächst alle offenen Rechnungen zu einem Debitor. Diese
|
|
* Rechnungen werden in eine ChildItems Collection überführt. Der User kann nun
|
|
* im Interface einzelne Rechnungen selektieren. Wird das Workitem gespeichert,
|
|
* errechnet der Controller die selectieren Invoices und verknpüft diese final
|
|
* mit dem Zahlungseingang.
|
|
*
|
|
*
|
|
* @author rsoika
|
|
*
|
|
*/
|
|
@Named("opListController")
|
|
@ConversationScoped
|
|
public class OPListController implements Serializable {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
public static final int TASK_ERSTELLUNG = 1000;
|
|
|
|
private static Logger logger = Logger.getLogger(OPListController.class.getName());
|
|
|
|
private String lastDbtrNumber = null;
|
|
|
|
private String currencyFilter = "-";
|
|
private String lastCurrencyFilter = null;
|
|
|
|
private List<ItemCollection> invoiceList = null;
|
|
|
|
@Inject
|
|
protected WorkflowController workflowController;
|
|
|
|
@Inject
|
|
protected WorkflowService workflowService;
|
|
|
|
@Inject
|
|
ZahlungseingangService zahlungseingangService;
|
|
|
|
@Inject
|
|
protected DocumentService documentService;
|
|
|
|
@Inject
|
|
protected InvoiceService invoiceService;
|
|
|
|
@Inject
|
|
protected BusinessPartnerService businessPartnerService;
|
|
|
|
/**
|
|
* Diese Methode wird für Zahlungseingänge und Mahnläufe verwendet.
|
|
* <p>
|
|
* Die Methode liefert die Rechnungen zur gegebenen dbtrNumber. Die Methode
|
|
* nutzt einen lokalen cache um die Zugriffe zu beschleunigen.
|
|
* <p>
|
|
* Befindet sich ein Zahlungseingang in Erstellung (Task=1000) werden alle
|
|
* offenen Rechnungen geholt.
|
|
* <p>
|
|
* Befindet sich ein Zahlungseingang nicht mehr in erstellung werden nur die
|
|
* Rechnugnen aus $workitemRef geholt!
|
|
* <p>
|
|
* Bei verwendung im Mahnlauf werden zusätzlich auch alle diese Rechnungen
|
|
* vorselektiert (Anforderung von Mary Mwangi). D.h. es werden alle Checkboxen
|
|
* in der Maske 'selection_opliste_Mahnluaf' angewählt. D.h auch, dass man ggf.
|
|
* Rechnungen manuell delselktieren muss, wenn man diese nicht im Mahnlauf haben
|
|
* will.
|
|
* <p>
|
|
* Beim Mahnlauf werden Inkasso Rechnungen ausgenommen.
|
|
*
|
|
*
|
|
* @param _dbtrNumber
|
|
* @return
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
public List<ItemCollection> getInvoices(String _dbtrNumber) {
|
|
|
|
// if last dbtr number is not equal then reset the current list....
|
|
if (invoiceList != null && //
|
|
(lastDbtrNumber == null
|
|
|| !lastDbtrNumber.equals(_dbtrNumber) //
|
|
|| lastCurrencyFilter == null
|
|
|| !lastCurrencyFilter.equals(currencyFilter)) //
|
|
) {
|
|
invoiceList = null;
|
|
}
|
|
|
|
if (invoiceList != null) {
|
|
return invoiceList;
|
|
}
|
|
if (_dbtrNumber == null) {
|
|
return new ArrayList<ItemCollection>();
|
|
}
|
|
long l = System.currentTimeMillis();
|
|
logger.info("...compute getInvoices...");
|
|
// Compute all open invoices if TASK_ERSTELLUNG....
|
|
if (workflowController.getWorkitem().getTaskID() == 0
|
|
|| workflowController.getWorkitem().getTaskID() == TASK_ERSTELLUNG) {
|
|
|
|
// return empty list if dbtr is not set
|
|
if (_dbtrNumber == null || _dbtrNumber.isEmpty()) {
|
|
invoiceList = new ArrayList<ItemCollection>();
|
|
return invoiceList;
|
|
}
|
|
|
|
// if last dbtr number is equal then return the current list....
|
|
if (invoiceList != null && //
|
|
lastDbtrNumber != null && lastDbtrNumber.equals(_dbtrNumber) && //
|
|
lastCurrencyFilter != null && lastCurrencyFilter.equals(currencyFilter) //
|
|
) {
|
|
return invoiceList;
|
|
}
|
|
|
|
// load new invoice list....
|
|
lastDbtrNumber = _dbtrNumber;
|
|
lastCurrencyFilter = currencyFilter;
|
|
invoiceList = new ArrayList<ItemCollection>();
|
|
logger.fine("....loading open Invoices for " + _dbtrNumber);
|
|
List<ItemCollection> invoiceListTemp = businessPartnerService.findOutgoingInvoices(_dbtrNumber);
|
|
|
|
// Jetzt nur noch die Rechnungen nehmen die zum ausgewählten Währungsfilter
|
|
// passen
|
|
invoiceList = new ArrayList<ItemCollection>();
|
|
for (ItemCollection _invoice : invoiceListTemp) {
|
|
|
|
// Test if we have 'invoice.base.amount' and 'invoice.rate'
|
|
if (!_invoice.hasItem("invoice.base.amount")) {
|
|
_invoice.setItemValue("invoice.base.amount", 0.0);
|
|
}
|
|
if (!_invoice.hasItem("invoice.rate")) {
|
|
_invoice.setItemValue("invoice.rate", 0.0);
|
|
}
|
|
|
|
if (currencyFilter == null || currencyFilter.isEmpty() || currencyFilter.equals("-")) {
|
|
invoiceList.add(_invoice);
|
|
} else {
|
|
if (currencyFilter.equals(_invoice.getItemValueString("invoice.currency"))) {
|
|
invoiceList.add(_invoice);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Zahlugnseingang?
|
|
*
|
|
* Wir berechnen den saldo.
|
|
*/
|
|
if (workflowController.getWorkitem().getModelVersion().startsWith("zahlungseingang")) {
|
|
// berechnung des Basisumsatzes bei Fremdwährungen
|
|
for (ItemCollection invoice : invoiceList) {
|
|
float rate = invoice.getItemValueFloat("invoice.rate");
|
|
float maxSaldo = invoice.getItemValueFloat("invoice.saldo");
|
|
if (rate != 0) {
|
|
maxSaldo = InvoiceUtil.roundToFloat(maxSaldo / rate);
|
|
invoice.setItemValue("invoice.saldo.byrate", maxSaldo);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Mahnlauf ?
|
|
*
|
|
* Bei einem Mahnlauf selektieren wir alle Rechnungne immer vor. Das ist eine
|
|
* Anforderung von AGL Der Benutzer kann dann einzelne Rechnungen wieder
|
|
* abwählen.
|
|
*
|
|
* Eine Ausnahme ist hier nur wenn jemand auf Speichern oder mahnen drückt
|
|
* (Event = 10|20). Dann ändern wir die Liste nicht!
|
|
*
|
|
* Hinweis: in der Liste befinden sich keine Inkasso Rechnungen, da man diese
|
|
* nicht anwählen kann.
|
|
*/
|
|
if (workflowController.getWorkitem().getModelVersion().startsWith("mahnlauf")) {
|
|
|
|
// wir selektieren hier immer alle fälligen Rechnungen vor falls wir aus
|
|
// einer Rechnung mit dem Event 100 (Mahnlauf erstellen) kommen, oder
|
|
// wenn der Mahnlauf von außen gerate eben neu erzeugt wurde
|
|
if (workflowController.getWorkitem().getItemValueInteger("$lastevent") == 100
|
|
|| workflowController.getWorkitem().getItemValueInteger("$lastevent") == 0) {
|
|
List<String> intialSelection = new ArrayList<String>();
|
|
for (ItemCollection invoice : invoiceList) {
|
|
// ist die Rechnung fällig?
|
|
if ("workitem".equals(invoice.getType()) && invoice.getTaskID() >= 5100) {
|
|
intialSelection.add(invoice.getUniqueID());
|
|
}
|
|
}
|
|
workflowController.getWorkitem().setItemValue("$workitemref", intialSelection);
|
|
}
|
|
}
|
|
} else {
|
|
// We are no longer in TASK_ERSTELLUNG, so
|
|
// fetch only selected invoices
|
|
invoiceList = new ArrayList<ItemCollection>();
|
|
if (!workflowController.getWorkitem().isItemEmpty("$workitemref")) {
|
|
List<String> selection = workflowController.getWorkitem().getItemValue("$workitemref");
|
|
for (String id : selection) {
|
|
if (id != null && !id.isEmpty()) {
|
|
ItemCollection _invoice = documentService.load(id);
|
|
// Test if we have 'invoice.base.amount' and 'invoice.rate'
|
|
if (!_invoice.hasItem("invoice.base.amount")) {
|
|
_invoice.setItemValue("invoice.base.amount", 0.0);
|
|
}
|
|
if (!_invoice.hasItem("invoice.rate")) {
|
|
_invoice.setItemValue("invoice.rate", 0.0);
|
|
}
|
|
invoiceList.add(_invoice);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// finally we set the 'selection' item depending on the $workitemList
|
|
// and the payment amount form the 'payment.details'
|
|
if (invoiceList != null) {
|
|
List<String> selection = workflowController.getWorkitem().getItemValue("$workitemref");
|
|
List<ItemCollection> paymentList = zahlungseingangService
|
|
.loadPaymentDetails(workflowController.getWorkitem());
|
|
for (ItemCollection invoice : invoiceList) {
|
|
if (selection.contains(invoice.getUniqueID())) {
|
|
invoice.setItemValue("selected", true);
|
|
// set amount
|
|
for (ItemCollection payment : paymentList) {
|
|
if (invoice.getUniqueID().equals(payment.getUniqueID())) {
|
|
invoice.setItemValue("payment.amount", payment.getItemValue("payment.amount"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// empty list
|
|
invoiceList = new ArrayList<ItemCollection>();
|
|
}
|
|
|
|
logger.info("...compute getInvoices completed in " + (System.currentTimeMillis() - l) + "ms");
|
|
return invoiceList;
|
|
}
|
|
|
|
public void reset() {
|
|
invoiceList = null;
|
|
}
|
|
|
|
/**
|
|
* On Before Process we store the selected invoices in $worktiemRef
|
|
*
|
|
* @param workflowEvent
|
|
*/
|
|
public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) {
|
|
if (workflowEvent == null || workflowEvent.getWorkitem() == null) {
|
|
return;
|
|
}
|
|
// store a collection of child items if you are in a Zahlungseingang
|
|
if (workflowEvent.getWorkitem().getModelVersion().startsWith("zahlungseingang")
|
|
&& workflowEvent.getEventType() == WorkflowEvent.WORKITEM_BEFORE_PROCESS) {
|
|
updateChildList(workflowEvent.getWorkitem());
|
|
}
|
|
}
|
|
|
|
public ItemCollection loadInvoice(String id) {
|
|
return documentService.load(id);
|
|
}
|
|
|
|
/**
|
|
* Diese Methode aktualisiert das item ChildWOrkitems mit allen selektierten
|
|
* Invoices udn berechnet den payment total
|
|
*/
|
|
@SuppressWarnings("rawtypes")
|
|
public void updateChildList(ItemCollection workitem) {
|
|
double paymentTotal = 0;
|
|
List<Map> mapInvoiceItems = new ArrayList<Map>();
|
|
logger.fine("Convert child items into Map...");
|
|
// iterate over all order items..
|
|
List<String> selectionList = new ArrayList<String>();
|
|
for (ItemCollection invoice : invoiceList) {
|
|
if (invoice.getItemValueBoolean("selected")) {
|
|
logger.fine("calculate - " + invoice.getUniqueID());
|
|
selectionList.add(invoice.getUniqueID());
|
|
paymentTotal = paymentTotal + invoice.getItemValueDouble("payment.amount");
|
|
ItemCollection invoiceStub = new ItemCollection();
|
|
invoiceStub.setItemValue(WorkflowKernel.UNIQUEID, invoice.getUniqueID());
|
|
invoiceStub.setItemValue("payment.amount", invoice.getItemValue("payment.amount"));
|
|
mapInvoiceItems.add(invoiceStub.getAllItems());
|
|
|
|
}
|
|
}
|
|
|
|
// rond with 2 digits
|
|
workitem.replaceItemValue("payment.total", InvoiceUtil.round(paymentTotal));
|
|
// update childitems
|
|
workitem.replaceItemValue(ZahlungseingangService.ITEM_PAYMENT_DETAILS, mapInvoiceItems);
|
|
// Update $workitemref
|
|
workitem.setItemValue("$workitemref", selectionList);
|
|
}
|
|
|
|
/**
|
|
* Hilfsmethode delegates to ZahlungseingangServcie
|
|
*
|
|
* @param payment
|
|
* @return
|
|
*/
|
|
public List<ItemCollection> loadPaymentDetails(ItemCollection payment) {
|
|
return zahlungseingangService.loadPaymentDetails(payment);
|
|
}
|
|
|
|
/**
|
|
* Berechnet den gesammten OP Saldo
|
|
*
|
|
* @return
|
|
*/
|
|
public double calculateInvoiceTotal() {
|
|
double result = 0;
|
|
for (ItemCollection invoice : invoiceList) {
|
|
result = result + invoice.getItemValueDouble("invoice.total");
|
|
}
|
|
// rond with 2 digits
|
|
return InvoiceUtil.round(result);
|
|
|
|
}
|
|
|
|
/**
|
|
* Berechnet die Summer aller Rechnungen zu einer Währung. Es werden nur
|
|
* Rechnungen berücksichtigt, deren Haupt Währung der übergebenen Währung
|
|
* entspricht.
|
|
*
|
|
* @param currency
|
|
* @return
|
|
*/
|
|
public double calculateInvoiceTotal(String currency) {
|
|
double result = 0;
|
|
for (ItemCollection invoice : invoiceList) {
|
|
if (currency.equals(invoice.getItemValueString("invoice.currency"))) {
|
|
result = result + invoice.getItemValueDouble("invoice.total");
|
|
}
|
|
}
|
|
// round with 2 digits
|
|
return InvoiceUtil.round(result);
|
|
|
|
}
|
|
|
|
/**
|
|
* Berechnet den gesamten OP Saldo
|
|
*
|
|
* @return
|
|
*/
|
|
public double calculateInvoiceSaldo() {
|
|
double result = 0;
|
|
if (invoiceList != null) {
|
|
for (ItemCollection invoice : invoiceList) {
|
|
result = result + invoice.getItemValueDouble("invoice.saldo");
|
|
}
|
|
}
|
|
// round with 2 digits
|
|
return InvoiceUtil.round(result);
|
|
|
|
}
|
|
|
|
/**
|
|
* Berechnet den noch offenen Differenz vom Zahlbetrag
|
|
*
|
|
* @return
|
|
*/
|
|
public double calculatePaymentDifference() {
|
|
double paymentAmount = workflowController.getWorkitem().getItemValueDouble("payment.amount");
|
|
double paymentDifference = workflowController.getWorkitem().getItemValueDouble("payment.difference");
|
|
|
|
double paymentTotal = workflowController.getWorkitem().getItemValueDouble("payment.total");
|
|
// paymentAmount - calculateInvoiceSaldo();
|
|
double result = (paymentAmount + paymentDifference) - paymentTotal;
|
|
|
|
logger.fine("...new PaymentDifference=" + result);
|
|
// rond with 2 digits
|
|
return InvoiceUtil.round(result);
|
|
}
|
|
|
|
/**
|
|
* Berechnet den Zahlbetrag in der Hauswährung bei Fremdwährungen
|
|
*
|
|
* @return
|
|
*/
|
|
public double calculatePaymentSaldoMainCurrency() {
|
|
double result = 0;
|
|
if (invoiceList != null) {
|
|
for (ItemCollection invoice : invoiceList) {
|
|
double rate = invoice.getItemValueDouble("invoice.rate");
|
|
double pay = invoice.getItemValueDouble("payment.amount");
|
|
if (rate != 0) {
|
|
result = result + pay / rate;
|
|
} else {
|
|
result = result + pay;
|
|
}
|
|
}
|
|
}
|
|
// rond with 2 digits
|
|
return InvoiceUtil.round(result);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the reminder date is today or in the past
|
|
*
|
|
* @param uniqueid
|
|
* @return
|
|
*/
|
|
public boolean isInDue(String uniqueid) {
|
|
ItemCollection invoice = workflowService.getWorkItem(uniqueid);
|
|
LocalDate date = invoice.getItemValueLocalDate("invoice.reminder");
|
|
return date.compareTo(LocalDate.now()) <= 0;
|
|
}
|
|
|
|
public String getCurrencyFilter() {
|
|
return currencyFilter;
|
|
}
|
|
|
|
public void setCurrencyFilter(String currencyFilter) {
|
|
this.currencyFilter = currencyFilter;
|
|
}
|
|
|
|
public List<String> getCurrenciesOut() {
|
|
try {
|
|
return invoiceService.getCurrenciesOut();
|
|
} catch (PluginException e) {
|
|
return new ArrayList<String>();
|
|
}
|
|
}
|
|
|
|
public String getCurrenciesOutMain() {
|
|
try {
|
|
return invoiceService.getCurrenciesOutMain();
|
|
} catch (PluginException e) {
|
|
return "undefined currency";
|
|
}
|
|
}
|
|
|
|
}
|