Example usage for java.math BigDecimal negate

List of usage examples for java.math BigDecimal negate

Introduction

In this page you can find the example usage for java.math BigDecimal negate.

Prototype

public BigDecimal negate() 

Source Link

Document

Returns a BigDecimal whose value is (-this) , and whose scale is this.scale() .

Usage

From source file:org.ofbiz.accounting.invoice.InvoiceServices.java

public static Map<String, Object> updatePaymentApplicationDefBd(DispatchContext dctx,
        Map<String, Object> context) {
    Delegator delegator = dctx.getDelegator();
    Locale locale = (Locale) context.get("locale");

    if (DECIMALS == -1 || ROUNDING == -1) {
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingAritmeticPropertiesNotConfigured", locale));
    }/*from   w ww . j  ava  2 s .co m*/

    if (!context.containsKey("useHighestAmount")) {
        context.put("useHighestAmount", "Y");
    }

    String defaultInvoiceProcessing = EntityUtilProperties.getPropertyValue("AccountingConfig",
            "invoiceProcessing", delegator);

    boolean debug = true; // show processing messages in the log..or not....

    // a 'y' in invoiceProssesing will reverse the default processing
    String changeProcessing = (String) context.get("invoiceProcessing");
    String invoiceId = (String) context.get("invoiceId");
    String invoiceItemSeqId = (String) context.get("invoiceItemSeqId");
    String paymentId = (String) context.get("paymentId");
    String toPaymentId = (String) context.get("toPaymentId");
    String paymentApplicationId = (String) context.get("paymentApplicationId");
    BigDecimal amountApplied = (BigDecimal) context.get("amountApplied");
    String billingAccountId = (String) context.get("billingAccountId");
    String taxAuthGeoId = (String) context.get("taxAuthGeoId");
    String useHighestAmount = (String) context.get("useHighestAmount");

    List<String> errorMessageList = FastList.newInstance();

    if (debug)
        Debug.logInfo("updatePaymentApplicationDefBd input parameters..." + " defaultInvoiceProcessing: "
                + defaultInvoiceProcessing + " changeDefaultInvoiceProcessing: " + changeProcessing
                + " useHighestAmount: " + useHighestAmount + " paymentApplicationId: " + paymentApplicationId
                + " PaymentId: " + paymentId + " InvoiceId: " + invoiceId + " InvoiceItemSeqId: "
                + invoiceItemSeqId + " BillingAccountId: " + billingAccountId + " toPaymentId: " + toPaymentId
                + " amountApplied: " + amountApplied + " TaxAuthGeoId: " + taxAuthGeoId, module);

    if (changeProcessing == null) {
        changeProcessing = "N"; // not provided, so no change
    }

    boolean invoiceProcessing = true;
    if (defaultInvoiceProcessing.equals("YY")) {
        invoiceProcessing = true;
    } else if (defaultInvoiceProcessing.equals("NN")) {
        invoiceProcessing = false;
    } else if (defaultInvoiceProcessing.equals("Y")) {
        invoiceProcessing = !"Y".equals(changeProcessing);
    } else if (defaultInvoiceProcessing.equals("N")) {
        invoiceProcessing = "Y".equals(changeProcessing);
    }

    // on a new paymentApplication check if only billing or invoice or tax
    // id is provided not 2,3... BUT a combination of billingAccountId and invoiceId is permitted - that's how you use a
    // Billing Account to pay for an Invoice
    if (paymentApplicationId == null) {
        int count = 0;
        if (invoiceId != null)
            count++;
        if (toPaymentId != null)
            count++;
        if (billingAccountId != null)
            count++;
        if (taxAuthGeoId != null)
            count++;
        if ((billingAccountId != null) && (invoiceId != null))
            count--;
        if (count != 1) {
            errorMessageList.add(UtilProperties.getMessage(resource,
                    "AccountingSpecifyInvoiceToPaymentBillingAccountTaxGeoId", locale));
        }
    }

    // avoid null pointer exceptions.
    if (amountApplied == null)
        amountApplied = ZERO;
    // makes no sense to have an item numer without an invoice number
    if (invoiceId == null)
        invoiceItemSeqId = null;

    // retrieve all information and perform checking on the retrieved info.....

    // Payment.....
    BigDecimal paymentApplyAvailable = ZERO;
    // amount available on the payment reduced by the already applied amounts
    BigDecimal amountAppliedMax = ZERO;
    // the maximum that can be applied taking payment,invoice,invoiceitem,billing account in concideration
    // if maxApplied is missing, this value can be used,
    // Payment this should be checked after the invoice checking because it is possible the currency is changed
    GenericValue payment = null;
    String currencyUomId = null;
    if (paymentId == null || paymentId.equals("")) {
        errorMessageList
                .add(UtilProperties.getMessage(resource, "AccountingPaymentIdBlankNotSupplied", locale));
    } else {
        try {
            payment = EntityQuery.use(delegator).from("Payment").where("paymentId", paymentId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (payment == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentRecordNotFound",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        paymentApplyAvailable = payment.getBigDecimal("amount")
                .subtract(PaymentWorker.getPaymentApplied(payment)).setScale(DECIMALS, ROUNDING);

        if (payment.getString("statusId").equals("PMNT_CANCELLED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentCancelled",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        if (payment.getString("statusId").equals("PMNT_CONFIRMED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentConfirmed",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }

        currencyUomId = payment.getString("currencyUomId");

        // if the amount to apply is 0 give it amount the payment still need
        // to apply
        if (amountApplied.signum() == 0) {
            amountAppliedMax = paymentApplyAvailable;
        }

    }

    // the "TO" Payment.....
    BigDecimal toPaymentApplyAvailable = ZERO;
    GenericValue toPayment = null;
    if (toPaymentId != null && !toPaymentId.equals("")) {
        try {
            toPayment = EntityQuery.use(delegator).from("Payment").where("paymentId", toPaymentId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (toPayment == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentRecordNotFound",
                    UtilMisc.toMap("paymentId", toPaymentId), locale));
        }
        toPaymentApplyAvailable = toPayment.getBigDecimal("amount")
                .subtract(PaymentWorker.getPaymentApplied(toPayment)).setScale(DECIMALS, ROUNDING);

        if (toPayment.getString("statusId").equals("PMNT_CANCELLED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentCancelled",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        if (toPayment.getString("statusId").equals("PMNT_CONFIRMED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentConfirmed",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }

        // if the amount to apply is less then required by the payment reduce it
        if (amountAppliedMax.compareTo(toPaymentApplyAvailable) > 0) {
            amountAppliedMax = toPaymentApplyAvailable;
        }

        if (paymentApplicationId == null) {
            // only check for new application records, update on existing records is checked in the paymentApplication section
            if (toPaymentApplyAvailable.signum() == 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentAlreadyApplied",
                        UtilMisc.toMap("paymentId", toPaymentId), locale));
            } else {
                // check here for too much application if a new record is
                // added (paymentApplicationId == null)
                if (amountApplied.compareTo(toPaymentApplyAvailable) > 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentLessRequested",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    toPaymentApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                    currencyUomId),
                            locale));
                }
            }
        }

        // check if at least one send is the same as one receiver on the other payment
        if (!payment.getString("partyIdFrom").equals(toPayment.getString("partyIdTo"))
                && !payment.getString("partyIdTo").equals(toPayment.getString("partyIdFrom"))) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingFromPartySameToParty", locale));
        }

        if (debug)
            Debug.logInfo("toPayment info retrieved and checked...", module);
    }

    // assign payment to billing account if the invoice is assigned to this billing account
    if (invoiceId != null) {
        GenericValue invoice = null;
        try {
            invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (invoice == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotFound",
                    UtilMisc.toMap("invoiceId", invoiceId), locale));
        } else {
            if (invoice.getString("billingAccountId") != null) {
                billingAccountId = invoice.getString("billingAccountId");
            }
        }
    }

    // billing account
    GenericValue billingAccount = null;
    if (billingAccountId != null && !billingAccountId.equals("")) {
        try {
            billingAccount = EntityQuery.use(delegator).from("BillingAccount")
                    .where("billingAccountId", billingAccountId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (billingAccount == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingBillingAccountNotFound",
                    UtilMisc.toMap("billingAccountId", billingAccountId), locale));
        }
        // check the currency
        if (billingAccount.get("accountCurrencyUomId") != null && currencyUomId != null
                && !billingAccount.getString("accountCurrencyUomId").equals(currencyUomId)) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingBillingAccountCurrencyProblem",
                    UtilMisc.toMap("billingAccountId", billingAccountId, "accountCurrencyUomId",
                            billingAccount.getString("accountCurrencyUomId"), "paymentId", paymentId,
                            "paymentCurrencyUomId", currencyUomId),
                    locale));
        }

        if (debug)
            Debug.logInfo("Billing Account info retrieved and checked...", module);
    }

    // get the invoice (item) information
    BigDecimal invoiceApplyAvailable = ZERO;
    // amount available on the invoice reduced by the already applied amounts
    BigDecimal invoiceItemApplyAvailable = ZERO;
    // amount available on the invoiceItem reduced by the already applied amounts
    GenericValue invoice = null;
    GenericValue invoiceItem = null;
    if (invoiceId != null) {
        try {
            invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (invoice == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotFound",
                    UtilMisc.toMap("invoiceId", invoiceId), locale));
        } else { // check the invoice and when supplied the invoice item...

            if (invoice.getString("statusId").equals("INVOICE_CANCELLED")) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingInvoiceCancelledCannotApplyTo",
                                UtilMisc.toMap("invoiceId", invoiceId), locale));
            }

            // check the currency
            if (currencyUomId != null && invoice.get("currencyUomId") != null
                    && !currencyUomId.equals(invoice.getString("currencyUomId"))) {
                Debug.logInfo(
                        UtilProperties.getMessage(resource, "AccountingInvoicePaymentCurrencyProblem",
                                UtilMisc.toMap("invoiceCurrency", invoice.getString("currencyUomId"),
                                        "paymentCurrency", payment.getString("currencyUomId")),
                                locale),
                        module);
                Debug.logInfo("will try to apply payment on the actualCurrency amount on payment", module);

                if (payment.get("actualCurrencyAmount") == null || payment.get("actualCurrencyUomId") == null) {
                    errorMessageList.add(
                            "Actual amounts are required in the currency of the invoice to make this work....");
                } else {
                    currencyUomId = payment.getString("actualCurrencyUomId");
                    if (!currencyUomId.equals(invoice.getString("currencyUomId"))) {
                        errorMessageList.add("actual currency on payment (" + currencyUomId
                                + ") not the same as original invoice currency ("
                                + invoice.getString("currencyUomId") + ")");
                    }
                }
                paymentApplyAvailable = payment.getBigDecimal("actualCurrencyAmount")
                        .subtract(PaymentWorker.getPaymentApplied(payment)).setScale(DECIMALS, ROUNDING);
                if (amountApplied.signum() == 0) {
                    amountAppliedMax = paymentApplyAvailable;
                }
            }

            // check if the invoice already covered by payments
            BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice);
            invoiceApplyAvailable = InvoiceWorker.getInvoiceNotApplied(invoice);

            // adjust the amountAppliedMax value if required....
            if (invoiceApplyAvailable.compareTo(amountAppliedMax) < 0) {
                amountAppliedMax = invoiceApplyAvailable;
            }

            if (invoiceTotal.signum() == 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceTotalZero",
                        UtilMisc.toMap("invoiceId", invoiceId), locale));
            } else if (paymentApplicationId == null) {
                // only check for new records here...updates are checked in the paymentApplication section
                if (invoiceApplyAvailable.signum() == 0) {
                    errorMessageList
                            .add(UtilProperties.getMessage(resource, "AccountingInvoiceCompletelyApplied",
                                    UtilMisc.toMap("invoiceId", invoiceId), locale));
                }
                // check here for too much application if a new record(s) are
                // added (paymentApplicationId == null)
                else if (amountApplied.compareTo(invoiceApplyAvailable) > 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceLessRequested",
                            UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "invoiceApplyAvailable",
                                    invoiceApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                    invoice.getString("currencyUomId")),
                            locale));
                }
            }

            // check if at least one sender is the same as one receiver on the invoice
            if (!payment.getString("partyIdFrom").equals(invoice.getString("partyId"))
                    && !payment.getString("partyIdTo").equals(invoice.getString("partyIdFrom"))) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingFromPartySameToParty", locale));
            }

            if (debug)
                Debug.logInfo("Invoice info retrieved and checked ...", module);
        }

        // if provided check the invoice item.
        if (invoiceItemSeqId != null) {
            // when itemSeqNr not provided delay checking on invoiceItemSeqId
            try {
                invoiceItem = EntityQuery.use(delegator).from("InvoiceItem")
                        .where("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId).queryOne();
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(e.getMessage());
            }

            if (invoiceItem == null) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceItemNotFound",
                        UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId), locale));
            } else {
                if (invoice.get("currencyUomId") != null && currencyUomId != null
                        && !invoice.getString("currencyUomId").equals(currencyUomId)) {
                    errorMessageList.add(UtilProperties.getMessage(resource,
                            "AccountingInvoicePaymentCurrencyProblem", UtilMisc.toMap("paymentCurrencyId",
                                    currencyUomId, "itemCurrency", invoice.getString("currencyUomId")),
                            locale));
                }

                // get the invoice item applied value
                BigDecimal quantity = null;
                if (invoiceItem.get("quantity") == null) {
                    quantity = BigDecimal.ONE;
                } else {
                    quantity = invoiceItem.getBigDecimal("quantity").setScale(DECIMALS, ROUNDING);
                }
                invoiceItemApplyAvailable = invoiceItem.getBigDecimal("amount").multiply(quantity)
                        .setScale(DECIMALS, ROUNDING)
                        .subtract(InvoiceWorker.getInvoiceItemApplied(invoiceItem));
                // check here for too much application if a new record is added
                // (paymentApplicationId == null)
                if (paymentApplicationId == null && amountApplied.compareTo(invoiceItemApplyAvailable) > 0) {
                    // new record
                    errorMessageList.add("Invoice(" + invoiceId + ") item(" + invoiceItemSeqId + ") has  "
                            + invoiceItemApplyAvailable + " to apply but " + amountApplied + " is requested\n");
                    String uomId = invoice.getString("currencyUomId");
                    errorMessageList.add(UtilProperties.getMessage(resource,
                            "AccountingInvoiceItemLessRequested",
                            UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "invoiceItemSeqId",
                                    invoiceItemSeqId, "invoiceItemApplyAvailable", invoiceItemApplyAvailable,
                                    "amountApplied", amountApplied, "isoCode", uomId),
                            locale));
                }
            }
            if (debug)
                Debug.logInfo(
                        "InvoiceItem info retrieved and checked against the Invoice (currency and amounts) ...",
                        module);
        }
    }

    // check this at the end because the invoice can change the currency.......
    if (paymentApplicationId == null) {
        // only check for new application records, update on existing records is checked in the paymentApplication section
        if (paymentApplyAvailable.signum() == 0) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentAlreadyApplied",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        } else {
            // check here for too much application if a new record is
            // added (paymentApplicationId == null)
            if (amountApplied.compareTo(paymentApplyAvailable) > 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentLessRequested",
                        UtilMisc.<String, Object>toMap("paymentId", paymentId, "paymentApplyAvailable",
                                paymentApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                currencyUomId),
                        locale));
            }
        }
    }

    // get the application record if the applicationId is supplied if not
    // create empty record.
    BigDecimal newInvoiceApplyAvailable = invoiceApplyAvailable;
    // amount available on the invoice taking into account if the invoiceItemnumber has changed
    BigDecimal newInvoiceItemApplyAvailable = invoiceItemApplyAvailable;
    // amount available on the invoiceItem taking into account if the itemnumber has changed
    BigDecimal newToPaymentApplyAvailable = toPaymentApplyAvailable;
    BigDecimal newPaymentApplyAvailable = paymentApplyAvailable;
    GenericValue paymentApplication = null;
    if (paymentApplicationId == null) {
        paymentApplication = delegator.makeValue("PaymentApplication");
        // prepare for creation
    } else { // retrieve existing paymentApplication
        try {
            paymentApplication = EntityQuery.use(delegator).from("PaymentApplication")
                    .where("paymentApplicationId", paymentApplicationId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (paymentApplication == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentApplicationNotFound",
                    UtilMisc.toMap("paymentApplicationId", paymentApplicationId), locale));
            paymentApplicationId = null;
        } else {

            // if both invoiceId and BillingId is entered there was
            // obviously a change
            // only take the newly entered item, same for tax authority and toPayment
            if (paymentApplication.get("invoiceId") == null && invoiceId != null) {
                billingAccountId = null;
                taxAuthGeoId = null;
                toPaymentId = null;
            } else if (paymentApplication.get("toPaymentId") == null && toPaymentId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                taxAuthGeoId = null;
                billingAccountId = null;
            } else if (paymentApplication.get("billingAccountId") == null && billingAccountId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                toPaymentId = null;
                taxAuthGeoId = null;
            } else if (paymentApplication.get("taxAuthGeoId") == null && taxAuthGeoId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                toPaymentId = null;
                billingAccountId = null;
            }

            // check if the payment for too much application if an existing
            // application record is changed
            if (paymentApplyAvailable.compareTo(ZERO) == 0) {
                newPaymentApplyAvailable = paymentApplyAvailable
                        .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                        .setScale(DECIMALS, ROUNDING);
            } else {
                newPaymentApplyAvailable = paymentApplyAvailable.add(paymentApplyAvailable)
                        .subtract(amountApplied).setScale(DECIMALS, ROUNDING);
            }
            if (newPaymentApplyAvailable.compareTo(ZERO) < 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                        UtilMisc.<String, Object>toMap("paymentId", paymentId, "paymentApplyAvailable",
                                paymentApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")),
                                "amountApplied", amountApplied),
                        locale));
            }

            if (invoiceId != null) {
                // only when we are processing an invoice on existing paymentApplication check invoice item for to much application if the invoice
                // number did not change
                if (invoiceId.equals(paymentApplication.getString("invoiceId"))) {
                    // check if both the itemNumbers are null then this is a
                    // record for the whole invoice
                    if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") == null) {
                        newInvoiceApplyAvailable = invoiceApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (invoiceApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList.add(UtilProperties.getMessage(resource,
                                    "AccountingInvoiceNotEnough", UtilMisc.<String, Object>toMap("tooMuch",
                                            newInvoiceApplyAvailable.negate(), "invoiceId", invoiceId),
                                    locale));
                        }
                    } else if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") != null) {
                        // check if the item number changed from a real Item number to a null value
                        newInvoiceApplyAvailable = invoiceApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (invoiceApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList.add(UtilProperties.getMessage(resource,
                                    "AccountingInvoiceNotEnough", UtilMisc.<String, Object>toMap("tooMuch",
                                            newInvoiceApplyAvailable.negate(), "invoiceId", invoiceId),
                                    locale));
                        }
                    } else if (invoiceItemSeqId != null && paymentApplication.get("invoiceItemSeqId") == null) {
                        // check if the item number changed from a null value to
                        // a real Item number
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    } else if (invoiceItemSeqId.equals(paymentApplication.getString("invoiceItemSeqId"))) {
                        // check if the real item numbers the same
                        // item number the same numeric value
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    } else {
                        // item number changed only check new item
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.add(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    }

                    // if the amountApplied = 0 give it the higest possible
                    // value
                    if (amountApplied.signum() == 0) {
                        if (newInvoiceItemApplyAvailable.compareTo(newPaymentApplyAvailable) < 0) {
                            amountApplied = newInvoiceItemApplyAvailable;
                            // from the item number
                        } else {
                            amountApplied = newPaymentApplyAvailable;
                            // from the payment
                        }
                    }

                    // check the invoice
                    newInvoiceApplyAvailable = invoiceApplyAvailable
                            .add(paymentApplication.getBigDecimal("amountApplied").subtract(amountApplied))
                            .setScale(DECIMALS, ROUNDING);
                    if (newInvoiceApplyAvailable.compareTo(ZERO) < 0) {
                        errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotEnough",
                                UtilMisc.<String, Object>toMap("tooMuch",
                                        invoiceApplyAvailable
                                                .add(paymentApplication.getBigDecimal("amountApplied"))
                                                .subtract(amountApplied),
                                        "invoiceId", invoiceId),
                                locale));
                    }
                }
            }

            // check the toPayment account when only the amountApplied has
            // changed,
            if (toPaymentId != null && toPaymentId.equals(paymentApplication.getString("toPaymentId"))) {
                newToPaymentApplyAvailable = toPaymentApplyAvailable
                        .subtract(paymentApplication.getBigDecimal("amountApplied")).add(amountApplied)
                        .setScale(DECIMALS, ROUNDING);
                if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    newToPaymentApplyAvailable, "amountApplied", amountApplied),
                            locale));
                }
            } else if (toPaymentId != null) {
                // billing account entered number has changed so we have to
                // check the new billing account number.
                newToPaymentApplyAvailable = toPaymentApplyAvailable.add(amountApplied).setScale(DECIMALS,
                        ROUNDING);
                if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    newToPaymentApplyAvailable, "amountApplied", amountApplied),
                            locale));
                }

            }
        }
        if (debug)
            Debug.logInfo("paymentApplication record info retrieved and checked...", module);
    }

    // show the maximumus what can be added in the payment application file.
    String toMessage = null; // prepare for success message
    if (debug) {
        String extra = "";
        if (invoiceItemSeqId != null) {
            extra = " Invoice item(" + invoiceItemSeqId + ") amount not yet applied: "
                    + newInvoiceItemApplyAvailable;
        }
        Debug.logInfo("checking finished, start processing with the following data... ", module);
        if (invoiceId != null) {
            Debug.logInfo(" Invoice(" + invoiceId + ") amount not yet applied: " + newInvoiceApplyAvailable
                    + extra + " Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable
                    + " Requested amount to apply:" + amountApplied, module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoice",
                    UtilMisc.toMap("invoiceId", invoiceId), locale);
            if (extra.length() > 0)
                toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoiceItem",
                        UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId), locale);
        }
        if (toPaymentId != null) {
            Debug.logInfo(" toPayment(" + toPaymentId + ") amount not yet applied: "
                    + newToPaymentApplyAvailable + " Payment(" + paymentId + ") amount not yet applied: "
                    + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToPayment",
                    UtilMisc.toMap("paymentId", toPaymentId), locale);
        }
        if (taxAuthGeoId != null) {
            Debug.logInfo(
                    " taxAuthGeoId(" + taxAuthGeoId + ")  Payment(" + paymentId + ") amount not yet applied: "
                            + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied,
                    module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToTax",
                    UtilMisc.toMap("taxAuthGeoId", taxAuthGeoId), locale);
        }
    }
    // if the amount to apply was not provided or was zero fill it with the maximum possible and provide information to the user
    if (amountApplied.signum() == 0 && useHighestAmount.equals("Y")) {
        amountApplied = newPaymentApplyAvailable;
        if (invoiceId != null && newInvoiceApplyAvailable.compareTo(amountApplied) < 0) {
            amountApplied = newInvoiceApplyAvailable;
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoice",
                    UtilMisc.toMap("invoiceId", invoiceId), locale);
        }
        if (toPaymentId != null && newToPaymentApplyAvailable.compareTo(amountApplied) < 0) {
            amountApplied = newToPaymentApplyAvailable;
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToPayment",
                    UtilMisc.toMap("paymentId", toPaymentId), locale);
        }
    }

    String successMessage = null;
    if (amountApplied.signum() == 0) {
        errorMessageList.add(UtilProperties.getMessage(resource, "AccountingNoAmount", locale));
    } else {
        successMessage = UtilProperties.getMessage(resource, "AccountingApplicationSuccess",
                UtilMisc.<String, Object>toMap("amountApplied", amountApplied, "paymentId", paymentId,
                        "isoCode", currencyUomId, "toMessage", toMessage),
                locale);
    }
    // report error messages if any
    if (errorMessageList.size() > 0) {
        return ServiceUtil.returnError(errorMessageList);
    }

    // ============ start processing ======================
    // if the application is specified it is easy, update the existing record only
    if (paymentApplicationId != null) {
        // record is already retrieved previously
        if (debug)
            Debug.logInfo("Process an existing paymentApplication record: " + paymentApplicationId, module);
        // update the current record
        paymentApplication.set("invoiceId", invoiceId);
        paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId);
        paymentApplication.set("paymentId", paymentId);
        paymentApplication.set("toPaymentId", toPaymentId);
        paymentApplication.set("amountApplied", amountApplied);
        paymentApplication.set("billingAccountId", billingAccountId);
        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
        return storePaymentApplication(delegator, paymentApplication, locale);
    }

    // if no invoice sequence number is provided it assumed the requested paymentAmount will be
    // spread over the invoice starting with the lowest sequence number if
    // itemprocessing is on otherwise create one record
    if (invoiceId != null && paymentId != null && (invoiceItemSeqId == null)) {
        if (invoiceProcessing) {
            // create only a single record with a null seqId
            if (debug)
                Debug.logInfo("Try to allocate the payment to the invoice as a whole", module);
            paymentApplication.set("paymentId", paymentId);
            paymentApplication.set("toPaymentId", null);
            paymentApplication.set("invoiceId", invoiceId);
            paymentApplication.set("invoiceItemSeqId", null);
            paymentApplication.set("toPaymentId", null);
            paymentApplication.set("amountApplied", amountApplied);
            paymentApplication.set("billingAccountId", billingAccountId);
            paymentApplication.set("taxAuthGeoId", null);
            if (debug)
                Debug.logInfo("creating new paymentapplication", module);
            return storePaymentApplication(delegator, paymentApplication, locale);
        } else { // spread the amount over every single item number
            if (debug)
                Debug.logInfo("Try to allocate the payment to the itemnumbers of the invoice", module);
            // get the invoice items
            List<GenericValue> invoiceItems = null;
            try {
                invoiceItems = EntityQuery.use(delegator).from("InvoiceItem").where("invoiceId", invoiceId)
                        .queryList();
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(e.getMessage());
            }
            if (invoiceItems.size() == 0) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingNoInvoiceItemsFoundForInvoice",
                                UtilMisc.toMap("invoiceId", invoiceId), locale));
                return ServiceUtil.returnError(errorMessageList);
            } else { // we found some invoice items, start processing....
                // check if the user want to apply a smaller amount than the maximum possible on the payment
                if (amountApplied.signum() != 0 && amountApplied.compareTo(paymentApplyAvailable) < 0) {
                    paymentApplyAvailable = amountApplied;
                }
                for (GenericValue currentInvoiceItem : invoiceItems) {
                    if (paymentApplyAvailable.compareTo(ZERO) > 0) {
                        break;
                    }
                    if (debug)
                        Debug.logInfo(
                                "Start processing item: " + currentInvoiceItem.getString("invoiceItemSeqId"),
                                module);
                    BigDecimal itemQuantity = BigDecimal.ONE;
                    if (currentInvoiceItem.get("quantity") != null
                            && currentInvoiceItem.getBigDecimal("quantity").signum() != 0) {
                        itemQuantity = new BigDecimal(currentInvoiceItem.getString("quantity"))
                                .setScale(DECIMALS, ROUNDING);
                    }
                    BigDecimal itemAmount = currentInvoiceItem.getBigDecimal("amount").setScale(DECIMALS,
                            ROUNDING);
                    BigDecimal itemTotal = itemAmount.multiply(itemQuantity).setScale(DECIMALS, ROUNDING);

                    // get the application(s) already allocated to this
                    // item, if available
                    List<GenericValue> paymentApplications = null;
                    try {
                        paymentApplications = currentInvoiceItem.getRelated("PaymentApplication", null, null,
                                false);
                    } catch (GenericEntityException e) {
                        return ServiceUtil.returnError(e.getMessage());
                    }
                    BigDecimal tobeApplied = ZERO;
                    // item total amount - already applied (if any)
                    BigDecimal alreadyApplied = ZERO;
                    if (UtilValidate.isNotEmpty(paymentApplications)) {
                        // application(s) found, add them all together
                        Iterator<GenericValue> p = paymentApplications.iterator();
                        while (p.hasNext()) {
                            paymentApplication = p.next();
                            alreadyApplied = alreadyApplied.add(paymentApplication
                                    .getBigDecimal("amountApplied").setScale(DECIMALS, ROUNDING));
                        }
                        tobeApplied = itemTotal.subtract(alreadyApplied).setScale(DECIMALS, ROUNDING);
                    } else {
                        // no application connected yet
                        tobeApplied = itemTotal;
                    }
                    if (debug)
                        Debug.logInfo("tobeApplied:(" + tobeApplied + ") = " + "itemTotal(" + itemTotal
                                + ") - alreadyApplied(" + alreadyApplied
                                + ") but not more then (nonapplied) paymentAmount(" + paymentApplyAvailable
                                + ")", module);

                    if (tobeApplied.signum() == 0) {
                        // invoiceItem already fully applied so look at the next one....
                        continue;
                    }

                    if (paymentApplyAvailable.compareTo(tobeApplied) > 0) {
                        paymentApplyAvailable = paymentApplyAvailable.subtract(tobeApplied);
                    } else {
                        tobeApplied = paymentApplyAvailable;
                        paymentApplyAvailable = ZERO;
                    }

                    // create application payment record but check currency
                    // first if supplied
                    if (invoice.get("currencyUomId") != null && currencyUomId != null
                            && !invoice.getString("currencyUomId").equals(currencyUomId)) {
                        errorMessageList.add("Payment currency (" + currencyUomId + ") and invoice currency("
                                + invoice.getString("currencyUomId") + ") not the same\n");
                    } else {
                        paymentApplication.set("paymentApplicationId", null);
                        // make sure we get a new record
                        paymentApplication.set("invoiceId", invoiceId);
                        paymentApplication.set("invoiceItemSeqId",
                                currentInvoiceItem.getString("invoiceItemSeqId"));
                        paymentApplication.set("paymentId", paymentId);
                        paymentApplication.set("toPaymentId", toPaymentId);
                        paymentApplication.set("amountApplied", tobeApplied);
                        paymentApplication.set("billingAccountId", billingAccountId);
                        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
                        storePaymentApplication(delegator, paymentApplication, locale);
                    }

                    // check if either the invoice or the payment is fully
                    // applied, when yes change the status to paid
                    // which triggers the ledger routines....
                    /*
                     * if
                     * (InvoiceWorker.getInvoiceTotal(invoice).equals(InvoiceWorker.getInvoiceApplied(invoice))) {
                     * try { dispatcher.runSync("setInvoiceStatus",
                     * UtilMisc.toMap("invoiceId",invoiceId,"statusId","INVOICE_PAID")); }
                     * catch (GenericServiceException e1) {
                     * Debug.logError(e1, "Error updating invoice status",
                     * module); } }
                     *
                     * if
                     * (payment.getBigDecimal("amount").equals(PaymentWorker.getPaymentApplied(payment))) {
                     * GenericValue appliedPayment = (GenericValue)
                     * delegator.makeValue("Payment",
                     * UtilMisc.toMap("paymentId",paymentId,"statusId","INVOICE_PAID"));
                     * try { appliedPayment.store(); } catch
                     * (GenericEntityException e) {
                     * ServiceUtil.returnError(e.getMessage()); } }
                     */
                }

                if (errorMessageList.size() > 0) {
                    return ServiceUtil.returnError(errorMessageList);
                } else {
                    if (successMessage != null) {
                        return ServiceUtil.returnSuccess(successMessage);
                    } else {
                        return ServiceUtil.returnSuccess();
                    }
                }
            }
        }
    }

    // if no paymentApplicationId supplied create a new record with the data
    // supplied...
    if (paymentApplicationId == null && amountApplied != null) {
        paymentApplication.set("paymentApplicationId", paymentApplicationId);
        paymentApplication.set("invoiceId", invoiceId);
        paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId);
        paymentApplication.set("paymentId", paymentId);
        paymentApplication.set("toPaymentId", toPaymentId);
        paymentApplication.set("amountApplied", amountApplied);
        paymentApplication.set("billingAccountId", billingAccountId);
        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
        return storePaymentApplication(delegator, paymentApplication, locale);
    }

    // should never come here...
    errorMessageList.add(
            UtilProperties.getMessage(resource, "AccountingPaymentApplicationParameterUnsuitable", locale));
    errorMessageList
            .add(UtilProperties.getMessage(resource, "AccountingPaymentApplicationParameterListUnsuitable",
                    UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId, "paymentId",
                            paymentId, "toPaymentId", toPaymentId, "paymentApplicationId", paymentApplicationId,
                            "amountApplied", amountApplied),
                    locale));
    return ServiceUtil.returnError(errorMessageList);
}

From source file:org.apache.ofbiz.accounting.invoice.InvoiceServices.java

public static Map<String, Object> updatePaymentApplicationDefBd(DispatchContext dctx,
        Map<String, Object> context) {
    Delegator delegator = dctx.getDelegator();
    Locale locale = (Locale) context.get("locale");

    if (DECIMALS == -1 || ROUNDING == -1) {
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingAritmeticPropertiesNotConfigured", locale));
    }//from   w w w. ja v  a 2s .c o m

    if (!context.containsKey("useHighestAmount")) {
        context.put("useHighestAmount", "Y");
    }

    String defaultInvoiceProcessing = EntityUtilProperties.getPropertyValue("accounting", "invoiceProcessing",
            delegator);

    boolean debug = true; // show processing messages in the log..or not....

    // a 'y' in invoiceProssesing will reverse the default processing
    String changeProcessing = (String) context.get("invoiceProcessing");
    String invoiceId = (String) context.get("invoiceId");
    String invoiceItemSeqId = (String) context.get("invoiceItemSeqId");
    String paymentId = (String) context.get("paymentId");
    String toPaymentId = (String) context.get("toPaymentId");
    String paymentApplicationId = (String) context.get("paymentApplicationId");
    BigDecimal amountApplied = (BigDecimal) context.get("amountApplied");
    String billingAccountId = (String) context.get("billingAccountId");
    String taxAuthGeoId = (String) context.get("taxAuthGeoId");
    String useHighestAmount = (String) context.get("useHighestAmount");

    List<String> errorMessageList = new LinkedList<String>();

    if (debug)
        Debug.logInfo("updatePaymentApplicationDefBd input parameters..." + " defaultInvoiceProcessing: "
                + defaultInvoiceProcessing + " changeDefaultInvoiceProcessing: " + changeProcessing
                + " useHighestAmount: " + useHighestAmount + " paymentApplicationId: " + paymentApplicationId
                + " PaymentId: " + paymentId + " InvoiceId: " + invoiceId + " InvoiceItemSeqId: "
                + invoiceItemSeqId + " BillingAccountId: " + billingAccountId + " toPaymentId: " + toPaymentId
                + " amountApplied: " + amountApplied + " TaxAuthGeoId: " + taxAuthGeoId, module);

    if (changeProcessing == null) {
        changeProcessing = "N"; // not provided, so no change
    }

    boolean invoiceProcessing = true;
    if (defaultInvoiceProcessing.equals("YY")) {
        invoiceProcessing = true;
    } else if (defaultInvoiceProcessing.equals("NN")) {
        invoiceProcessing = false;
    } else if (defaultInvoiceProcessing.equals("Y")) {
        invoiceProcessing = !"Y".equals(changeProcessing);
    } else if (defaultInvoiceProcessing.equals("N")) {
        invoiceProcessing = "Y".equals(changeProcessing);
    }

    // on a new paymentApplication check if only billing or invoice or tax
    // id is provided not 2,3... BUT a combination of billingAccountId and invoiceId is permitted - that's how you use a
    // Billing Account to pay for an Invoice
    if (paymentApplicationId == null) {
        int count = 0;
        if (invoiceId != null)
            count++;
        if (toPaymentId != null)
            count++;
        if (billingAccountId != null)
            count++;
        if (taxAuthGeoId != null)
            count++;
        if ((billingAccountId != null) && (invoiceId != null))
            count--;
        if (count != 1) {
            errorMessageList.add(UtilProperties.getMessage(resource,
                    "AccountingSpecifyInvoiceToPaymentBillingAccountTaxGeoId", locale));
        }
    }

    // avoid null pointer exceptions.
    if (amountApplied == null)
        amountApplied = ZERO;
    // makes no sense to have an item numer without an invoice number
    if (invoiceId == null)
        invoiceItemSeqId = null;

    // retrieve all information and perform checking on the retrieved info.....

    // Payment.....
    BigDecimal paymentApplyAvailable = ZERO;
    // amount available on the payment reduced by the already applied amounts
    BigDecimal amountAppliedMax = ZERO;
    // the maximum that can be applied taking payment,invoice,invoiceitem,billing account in concideration
    // if maxApplied is missing, this value can be used,
    // Payment this should be checked after the invoice checking because it is possible the currency is changed
    GenericValue payment = null;
    String currencyUomId = null;
    if (paymentId == null || paymentId.equals("")) {
        errorMessageList
                .add(UtilProperties.getMessage(resource, "AccountingPaymentIdBlankNotSupplied", locale));
    } else {
        try {
            payment = EntityQuery.use(delegator).from("Payment").where("paymentId", paymentId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (payment == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentRecordNotFound",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        paymentApplyAvailable = payment.getBigDecimal("amount")
                .subtract(PaymentWorker.getPaymentApplied(payment)).setScale(DECIMALS, ROUNDING);

        if (payment.getString("statusId").equals("PMNT_CANCELLED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentCancelled",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        if (payment.getString("statusId").equals("PMNT_CONFIRMED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentConfirmed",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }

        currencyUomId = payment.getString("currencyUomId");

        // if the amount to apply is 0 give it amount the payment still need
        // to apply
        if (amountApplied.signum() == 0) {
            amountAppliedMax = paymentApplyAvailable;
        }

    }

    // the "TO" Payment.....
    BigDecimal toPaymentApplyAvailable = ZERO;
    GenericValue toPayment = null;
    if (toPaymentId != null && !toPaymentId.equals("")) {
        try {
            toPayment = EntityQuery.use(delegator).from("Payment").where("paymentId", toPaymentId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (toPayment == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentRecordNotFound",
                    UtilMisc.toMap("paymentId", toPaymentId), locale));
        }
        toPaymentApplyAvailable = toPayment.getBigDecimal("amount")
                .subtract(PaymentWorker.getPaymentApplied(toPayment)).setScale(DECIMALS, ROUNDING);

        if (toPayment.getString("statusId").equals("PMNT_CANCELLED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentCancelled",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }
        if (toPayment.getString("statusId").equals("PMNT_CONFIRMED")) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentConfirmed",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        }

        // if the amount to apply is less then required by the payment reduce it
        if (amountAppliedMax.compareTo(toPaymentApplyAvailable) > 0) {
            amountAppliedMax = toPaymentApplyAvailable;
        }

        if (paymentApplicationId == null) {
            // only check for new application records, update on existing records is checked in the paymentApplication section
            if (toPaymentApplyAvailable.signum() == 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentAlreadyApplied",
                        UtilMisc.toMap("paymentId", toPaymentId), locale));
            } else {
                // check here for too much application if a new record is
                // added (paymentApplicationId == null)
                if (amountApplied.compareTo(toPaymentApplyAvailable) > 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentLessRequested",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    toPaymentApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                    currencyUomId),
                            locale));
                }
            }
        }

        // check if at least one send is the same as one receiver on the other payment
        if (!payment.getString("partyIdFrom").equals(toPayment.getString("partyIdTo"))
                && !payment.getString("partyIdTo").equals(toPayment.getString("partyIdFrom"))) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingFromPartySameToParty", locale));
        }

        if (debug)
            Debug.logInfo("toPayment info retrieved and checked...", module);
    }

    // assign payment to billing account if the invoice is assigned to this billing account
    if (invoiceId != null) {
        GenericValue invoice = null;
        try {
            invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (invoice == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotFound",
                    UtilMisc.toMap("invoiceId", invoiceId), locale));
        } else {
            if (invoice.getString("billingAccountId") != null) {
                billingAccountId = invoice.getString("billingAccountId");
            }
        }
    }

    // billing account
    GenericValue billingAccount = null;
    if (billingAccountId != null && !billingAccountId.equals("")) {
        try {
            billingAccount = EntityQuery.use(delegator).from("BillingAccount")
                    .where("billingAccountId", billingAccountId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        if (billingAccount == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingBillingAccountNotFound",
                    UtilMisc.toMap("billingAccountId", billingAccountId), locale));
        }
        // check the currency
        if (billingAccount.get("accountCurrencyUomId") != null && currencyUomId != null
                && !billingAccount.getString("accountCurrencyUomId").equals(currencyUomId)) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingBillingAccountCurrencyProblem",
                    UtilMisc.toMap("billingAccountId", billingAccountId, "accountCurrencyUomId",
                            billingAccount.getString("accountCurrencyUomId"), "paymentId", paymentId,
                            "paymentCurrencyUomId", currencyUomId),
                    locale));
        }

        if (debug)
            Debug.logInfo("Billing Account info retrieved and checked...", module);
    }

    // get the invoice (item) information
    BigDecimal invoiceApplyAvailable = ZERO;
    // amount available on the invoice reduced by the already applied amounts
    BigDecimal invoiceItemApplyAvailable = ZERO;
    // amount available on the invoiceItem reduced by the already applied amounts
    GenericValue invoice = null;
    GenericValue invoiceItem = null;
    if (invoiceId != null) {
        try {
            invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (invoice == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotFound",
                    UtilMisc.toMap("invoiceId", invoiceId), locale));
        } else { // check the invoice and when supplied the invoice item...

            if (invoice.getString("statusId").equals("INVOICE_CANCELLED")) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingInvoiceCancelledCannotApplyTo",
                                UtilMisc.toMap("invoiceId", invoiceId), locale));
            }

            // check the currency
            if (currencyUomId != null && invoice.get("currencyUomId") != null
                    && !currencyUomId.equals(invoice.getString("currencyUomId"))) {
                Debug.logInfo(
                        UtilProperties.getMessage(resource, "AccountingInvoicePaymentCurrencyProblem",
                                UtilMisc.toMap("invoiceCurrency", invoice.getString("currencyUomId"),
                                        "paymentCurrency", payment.getString("currencyUomId")),
                                locale),
                        module);
                Debug.logInfo("will try to apply payment on the actualCurrency amount on payment", module);

                if (payment.get("actualCurrencyAmount") == null || payment.get("actualCurrencyUomId") == null) {
                    errorMessageList.add(
                            "Actual amounts are required in the currency of the invoice to make this work....");
                } else {
                    currencyUomId = payment.getString("actualCurrencyUomId");
                    if (!currencyUomId.equals(invoice.getString("currencyUomId"))) {
                        errorMessageList.add("actual currency on payment (" + currencyUomId
                                + ") not the same as original invoice currency ("
                                + invoice.getString("currencyUomId") + ")");
                    }
                }
                paymentApplyAvailable = payment.getBigDecimal("actualCurrencyAmount")
                        .subtract(PaymentWorker.getPaymentApplied(payment)).setScale(DECIMALS, ROUNDING);
                if (amountApplied.signum() == 0) {
                    amountAppliedMax = paymentApplyAvailable;
                }
            }

            // check if the invoice already covered by payments
            BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice);
            invoiceApplyAvailable = InvoiceWorker.getInvoiceNotApplied(invoice);

            // adjust the amountAppliedMax value if required....
            if (invoiceApplyAvailable.compareTo(amountAppliedMax) < 0) {
                amountAppliedMax = invoiceApplyAvailable;
            }

            if (invoiceTotal.signum() == 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceTotalZero",
                        UtilMisc.toMap("invoiceId", invoiceId), locale));
            } else if (paymentApplicationId == null) {
                // only check for new records here...updates are checked in the paymentApplication section
                if (invoiceApplyAvailable.signum() == 0) {
                    errorMessageList
                            .add(UtilProperties.getMessage(resource, "AccountingInvoiceCompletelyApplied",
                                    UtilMisc.toMap("invoiceId", invoiceId), locale));
                }
                // check here for too much application if a new record(s) are
                // added (paymentApplicationId == null)
                else if (amountApplied.compareTo(invoiceApplyAvailable) > 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceLessRequested",
                            UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "invoiceApplyAvailable",
                                    invoiceApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                    invoice.getString("currencyUomId")),
                            locale));
                }
            }

            // check if at least one sender is the same as one receiver on the invoice
            if (!payment.getString("partyIdFrom").equals(invoice.getString("partyId"))
                    && !payment.getString("partyIdTo").equals(invoice.getString("partyIdFrom"))) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingFromPartySameToParty", locale));
            }

            if (debug)
                Debug.logInfo("Invoice info retrieved and checked ...", module);
        }

        // if provided check the invoice item.
        if (invoiceItemSeqId != null) {
            // when itemSeqNr not provided delay checking on invoiceItemSeqId
            try {
                invoiceItem = EntityQuery.use(delegator).from("InvoiceItem")
                        .where("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId).queryOne();
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(e.getMessage());
            }

            if (invoiceItem == null) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceItemNotFound",
                        UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId), locale));
            } else {
                if (invoice.get("currencyUomId") != null && currencyUomId != null
                        && !invoice.getString("currencyUomId").equals(currencyUomId)) {
                    errorMessageList.add(UtilProperties.getMessage(resource,
                            "AccountingInvoicePaymentCurrencyProblem", UtilMisc.toMap("paymentCurrencyId",
                                    currencyUomId, "itemCurrency", invoice.getString("currencyUomId")),
                            locale));
                }

                // get the invoice item applied value
                BigDecimal quantity = null;
                if (invoiceItem.get("quantity") == null) {
                    quantity = BigDecimal.ONE;
                } else {
                    quantity = invoiceItem.getBigDecimal("quantity").setScale(DECIMALS, ROUNDING);
                }
                invoiceItemApplyAvailable = invoiceItem.getBigDecimal("amount").multiply(quantity)
                        .setScale(DECIMALS, ROUNDING)
                        .subtract(InvoiceWorker.getInvoiceItemApplied(invoiceItem));
                // check here for too much application if a new record is added
                if (paymentApplicationId == null && amountApplied.compareTo(invoiceItemApplyAvailable) > 0) {
                    // new record
                    errorMessageList.add("Invoice(" + invoiceId + ") item(" + invoiceItemSeqId + ") has  "
                            + invoiceItemApplyAvailable + " to apply but " + amountApplied + " is requested\n");
                    String uomId = invoice.getString("currencyUomId");
                    errorMessageList.add(UtilProperties.getMessage(resource,
                            "AccountingInvoiceItemLessRequested",
                            UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "invoiceItemSeqId",
                                    invoiceItemSeqId, "invoiceItemApplyAvailable", invoiceItemApplyAvailable,
                                    "amountApplied", amountApplied, "isoCode", uomId),
                            locale));
                }
            }
            if (debug)
                Debug.logInfo(
                        "InvoiceItem info retrieved and checked against the Invoice (currency and amounts) ...",
                        module);
        }
    }

    // check this at the end because the invoice can change the currency.......
    if (paymentApplicationId == null) {
        // only check for new application records, update on existing records is checked in the paymentApplication section
        if (paymentApplyAvailable.signum() == 0) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentAlreadyApplied",
                    UtilMisc.toMap("paymentId", paymentId), locale));
        } else {
            // check here for too much application if a new record is
            // added (paymentApplicationId == null)
            if (amountApplied.compareTo(paymentApplyAvailable) > 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentLessRequested",
                        UtilMisc.<String, Object>toMap("paymentId", paymentId, "paymentApplyAvailable",
                                paymentApplyAvailable, "amountApplied", amountApplied, "isoCode",
                                currencyUomId),
                        locale));
            }
        }
    }

    // get the application record if the applicationId is supplied if not
    // create empty record.
    BigDecimal newInvoiceApplyAvailable = invoiceApplyAvailable;
    // amount available on the invoice taking into account if the invoiceItemnumber has changed
    BigDecimal newInvoiceItemApplyAvailable = invoiceItemApplyAvailable;
    // amount available on the invoiceItem taking into account if the itemnumber has changed
    BigDecimal newToPaymentApplyAvailable = toPaymentApplyAvailable;
    BigDecimal newPaymentApplyAvailable = paymentApplyAvailable;
    GenericValue paymentApplication = null;
    if (paymentApplicationId == null) {
        paymentApplication = delegator.makeValue("PaymentApplication");
        // prepare for creation
    } else { // retrieve existing paymentApplication
        try {
            paymentApplication = EntityQuery.use(delegator).from("PaymentApplication")
                    .where("paymentApplicationId", paymentApplicationId).queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        if (paymentApplication == null) {
            errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentApplicationNotFound",
                    UtilMisc.toMap("paymentApplicationId", paymentApplicationId), locale));
            paymentApplicationId = null;
        } else {

            // if both invoiceId and BillingId is entered there was
            // obviously a change
            // only take the newly entered item, same for tax authority and toPayment
            if (paymentApplication.get("invoiceId") == null && invoiceId != null) {
                billingAccountId = null;
                taxAuthGeoId = null;
                toPaymentId = null;
            } else if (paymentApplication.get("toPaymentId") == null && toPaymentId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                taxAuthGeoId = null;
                billingAccountId = null;
            } else if (paymentApplication.get("billingAccountId") == null && billingAccountId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                toPaymentId = null;
                taxAuthGeoId = null;
            } else if (paymentApplication.get("taxAuthGeoId") == null && taxAuthGeoId != null) {
                invoiceId = null;
                invoiceItemSeqId = null;
                toPaymentId = null;
                billingAccountId = null;
            }

            // check if the payment for too much application if an existing
            // application record is changed
            if (paymentApplyAvailable.compareTo(ZERO) == 0) {
                newPaymentApplyAvailable = paymentApplyAvailable
                        .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                        .setScale(DECIMALS, ROUNDING);
            } else {
                newPaymentApplyAvailable = paymentApplyAvailable.add(paymentApplyAvailable)
                        .subtract(amountApplied).setScale(DECIMALS, ROUNDING);
            }
            if (newPaymentApplyAvailable.compareTo(ZERO) < 0) {
                errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                        UtilMisc.<String, Object>toMap("paymentId", paymentId, "paymentApplyAvailable",
                                paymentApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")),
                                "amountApplied", amountApplied),
                        locale));
            }

            if (invoiceId != null) {
                // only when we are processing an invoice on existing paymentApplication check invoice item for to much application if the invoice
                // number did not change
                if (invoiceId.equals(paymentApplication.getString("invoiceId"))) {
                    // check if both the itemNumbers are null then this is a
                    // record for the whole invoice
                    if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") == null) {
                        newInvoiceApplyAvailable = invoiceApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (invoiceApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList.add(UtilProperties.getMessage(resource,
                                    "AccountingInvoiceNotEnough", UtilMisc.<String, Object>toMap("tooMuch",
                                            newInvoiceApplyAvailable.negate(), "invoiceId", invoiceId),
                                    locale));
                        }
                    } else if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") != null) {
                        // check if the item number changed from a real Item number to a null value
                        newInvoiceApplyAvailable = invoiceApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (invoiceApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList.add(UtilProperties.getMessage(resource,
                                    "AccountingInvoiceNotEnough", UtilMisc.<String, Object>toMap("tooMuch",
                                            newInvoiceApplyAvailable.negate(), "invoiceId", invoiceId),
                                    locale));
                        }
                    } else if (invoiceItemSeqId != null && paymentApplication.get("invoiceItemSeqId") == null) {
                        // check if the item number changed from a null value to
                        // a real Item number
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    } else if (invoiceItemSeqId.equals(paymentApplication.getString("invoiceItemSeqId"))) {
                        // check if the real item numbers the same
                        // item number the same numeric value
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable
                                .add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    } else {
                        // item number changed only check new item
                        newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.add(amountApplied)
                                .setScale(DECIMALS, ROUNDING);
                        if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) {
                            errorMessageList
                                    .add(UtilProperties.getMessage(resource, "AccountingItemInvoiceNotEnough",
                                            UtilMisc.<String, Object>toMap("tooMuch",
                                                    newInvoiceItemApplyAvailable.negate(), "invoiceId",
                                                    invoiceId, "invoiceItemSeqId", invoiceItemSeqId),
                                            locale));
                        }
                    }

                    // if the amountApplied = 0 give it the higest possible
                    // value
                    if (amountApplied.signum() == 0) {
                        if (newInvoiceItemApplyAvailable.compareTo(newPaymentApplyAvailable) < 0) {
                            amountApplied = newInvoiceItemApplyAvailable;
                            // from the item number
                        } else {
                            amountApplied = newPaymentApplyAvailable;
                            // from the payment
                        }
                    }

                    // check the invoice
                    newInvoiceApplyAvailable = invoiceApplyAvailable
                            .add(paymentApplication.getBigDecimal("amountApplied").subtract(amountApplied))
                            .setScale(DECIMALS, ROUNDING);
                    if (newInvoiceApplyAvailable.compareTo(ZERO) < 0) {
                        errorMessageList.add(UtilProperties.getMessage(resource, "AccountingInvoiceNotEnough",
                                UtilMisc.<String, Object>toMap("tooMuch",
                                        invoiceApplyAvailable
                                                .add(paymentApplication.getBigDecimal("amountApplied"))
                                                .subtract(amountApplied),
                                        "invoiceId", invoiceId),
                                locale));
                    }
                }
            }

            // check the toPayment account when only the amountApplied has
            // changed,
            if (toPaymentId != null && toPaymentId.equals(paymentApplication.getString("toPaymentId"))) {
                newToPaymentApplyAvailable = toPaymentApplyAvailable
                        .subtract(paymentApplication.getBigDecimal("amountApplied")).add(amountApplied)
                        .setScale(DECIMALS, ROUNDING);
                if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    newToPaymentApplyAvailable, "amountApplied", amountApplied),
                            locale));
                }
            } else if (toPaymentId != null) {
                // billing account entered number has changed so we have to
                // check the new billing account number.
                newToPaymentApplyAvailable = toPaymentApplyAvailable.add(amountApplied).setScale(DECIMALS,
                        ROUNDING);
                if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) {
                    errorMessageList.add(UtilProperties.getMessage(resource, "AccountingPaymentNotEnough",
                            UtilMisc.<String, Object>toMap("paymentId", toPaymentId, "paymentApplyAvailable",
                                    newToPaymentApplyAvailable, "amountApplied", amountApplied),
                            locale));
                }

            }
        }
        if (debug)
            Debug.logInfo("paymentApplication record info retrieved and checked...", module);
    }

    // show the maximumus what can be added in the payment application file.
    String toMessage = null; // prepare for success message
    if (debug) {
        String extra = "";
        if (invoiceItemSeqId != null) {
            extra = " Invoice item(" + invoiceItemSeqId + ") amount not yet applied: "
                    + newInvoiceItemApplyAvailable;
        }
        Debug.logInfo("checking finished, start processing with the following data... ", module);
        if (invoiceId != null) {
            Debug.logInfo(" Invoice(" + invoiceId + ") amount not yet applied: " + newInvoiceApplyAvailable
                    + extra + " Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable
                    + " Requested amount to apply:" + amountApplied, module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoice",
                    UtilMisc.toMap("invoiceId", invoiceId), locale);
            if (extra.length() > 0)
                toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoiceItem",
                        UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId), locale);
        }
        if (toPaymentId != null) {
            Debug.logInfo(" toPayment(" + toPaymentId + ") amount not yet applied: "
                    + newToPaymentApplyAvailable + " Payment(" + paymentId + ") amount not yet applied: "
                    + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToPayment",
                    UtilMisc.toMap("paymentId", toPaymentId), locale);
        }
        if (taxAuthGeoId != null) {
            Debug.logInfo(
                    " taxAuthGeoId(" + taxAuthGeoId + ")  Payment(" + paymentId + ") amount not yet applied: "
                            + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied,
                    module);
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToTax",
                    UtilMisc.toMap("taxAuthGeoId", taxAuthGeoId), locale);
        }
    }
    // if the amount to apply was not provided or was zero fill it with the maximum possible and provide information to the user
    if (amountApplied.signum() == 0 && useHighestAmount.equals("Y")) {
        amountApplied = newPaymentApplyAvailable;
        if (invoiceId != null && newInvoiceApplyAvailable.compareTo(amountApplied) < 0) {
            amountApplied = newInvoiceApplyAvailable;
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToInvoice",
                    UtilMisc.toMap("invoiceId", invoiceId), locale);
        }
        if (toPaymentId != null && newToPaymentApplyAvailable.compareTo(amountApplied) < 0) {
            amountApplied = newToPaymentApplyAvailable;
            toMessage = UtilProperties.getMessage(resource, "AccountingApplicationToPayment",
                    UtilMisc.toMap("paymentId", toPaymentId), locale);
        }
    }

    String successMessage = null;
    if (amountApplied.signum() == 0) {
        errorMessageList.add(UtilProperties.getMessage(resource, "AccountingNoAmount", locale));
    } else {
        successMessage = UtilProperties.getMessage(resource, "AccountingApplicationSuccess",
                UtilMisc.<String, Object>toMap("amountApplied", amountApplied, "paymentId", paymentId,
                        "isoCode", currencyUomId, "toMessage", toMessage),
                locale);
    }
    // report error messages if any
    if (errorMessageList.size() > 0) {
        return ServiceUtil.returnError(errorMessageList);
    }

    // ============ start processing ======================
    // if the application is specified it is easy, update the existing record only
    if (paymentApplicationId != null) {
        // record is already retrieved previously
        if (debug)
            Debug.logInfo("Process an existing paymentApplication record: " + paymentApplicationId, module);
        // update the current record
        paymentApplication.set("invoiceId", invoiceId);
        paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId);
        paymentApplication.set("paymentId", paymentId);
        paymentApplication.set("toPaymentId", toPaymentId);
        paymentApplication.set("amountApplied", amountApplied);
        paymentApplication.set("billingAccountId", billingAccountId);
        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
        return storePaymentApplication(delegator, paymentApplication, locale);
    }

    // if no invoice sequence number is provided it assumed the requested paymentAmount will be
    // spread over the invoice starting with the lowest sequence number if
    // itemprocessing is on otherwise create one record
    if (invoiceId != null && paymentId != null && (invoiceItemSeqId == null)) {
        if (invoiceProcessing) {
            // create only a single record with a null seqId
            if (debug)
                Debug.logInfo("Try to allocate the payment to the invoice as a whole", module);
            paymentApplication.set("paymentId", paymentId);
            paymentApplication.set("toPaymentId", null);
            paymentApplication.set("invoiceId", invoiceId);
            paymentApplication.set("invoiceItemSeqId", null);
            paymentApplication.set("toPaymentId", null);
            paymentApplication.set("amountApplied", amountApplied);
            paymentApplication.set("billingAccountId", billingAccountId);
            paymentApplication.set("taxAuthGeoId", null);
            if (debug)
                Debug.logInfo("creating new paymentapplication", module);
            return storePaymentApplication(delegator, paymentApplication, locale);
        } else { // spread the amount over every single item number
            if (debug)
                Debug.logInfo("Try to allocate the payment to the itemnumbers of the invoice", module);
            // get the invoice items
            List<GenericValue> invoiceItems = null;
            try {
                invoiceItems = EntityQuery.use(delegator).from("InvoiceItem").where("invoiceId", invoiceId)
                        .queryList();
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(e.getMessage());
            }
            if (invoiceItems.size() == 0) {
                errorMessageList
                        .add(UtilProperties.getMessage(resource, "AccountingNoInvoiceItemsFoundForInvoice",
                                UtilMisc.toMap("invoiceId", invoiceId), locale));
                return ServiceUtil.returnError(errorMessageList);
            } else { // we found some invoice items, start processing....
                // check if the user want to apply a smaller amount than the maximum possible on the payment
                if (amountApplied.signum() != 0 && amountApplied.compareTo(paymentApplyAvailable) < 0) {
                    paymentApplyAvailable = amountApplied;
                }
                for (GenericValue currentInvoiceItem : invoiceItems) {
                    if (paymentApplyAvailable.compareTo(ZERO) > 0) {
                        break;
                    }
                    if (debug)
                        Debug.logInfo(
                                "Start processing item: " + currentInvoiceItem.getString("invoiceItemSeqId"),
                                module);
                    BigDecimal itemQuantity = BigDecimal.ONE;
                    if (currentInvoiceItem.get("quantity") != null
                            && currentInvoiceItem.getBigDecimal("quantity").signum() != 0) {
                        itemQuantity = new BigDecimal(currentInvoiceItem.getString("quantity"))
                                .setScale(DECIMALS, ROUNDING);
                    }
                    BigDecimal itemAmount = currentInvoiceItem.getBigDecimal("amount").setScale(DECIMALS,
                            ROUNDING);
                    BigDecimal itemTotal = itemAmount.multiply(itemQuantity).setScale(DECIMALS, ROUNDING);

                    // get the application(s) already allocated to this
                    // item, if available
                    List<GenericValue> paymentApplications = null;
                    try {
                        paymentApplications = currentInvoiceItem.getRelated("PaymentApplication", null, null,
                                false);
                    } catch (GenericEntityException e) {
                        return ServiceUtil.returnError(e.getMessage());
                    }
                    BigDecimal tobeApplied = ZERO;
                    // item total amount - already applied (if any)
                    BigDecimal alreadyApplied = ZERO;
                    if (UtilValidate.isNotEmpty(paymentApplications)) {
                        // application(s) found, add them all together
                        Iterator<GenericValue> p = paymentApplications.iterator();
                        while (p.hasNext()) {
                            paymentApplication = p.next();
                            alreadyApplied = alreadyApplied.add(paymentApplication
                                    .getBigDecimal("amountApplied").setScale(DECIMALS, ROUNDING));
                        }
                        tobeApplied = itemTotal.subtract(alreadyApplied).setScale(DECIMALS, ROUNDING);
                    } else {
                        // no application connected yet
                        tobeApplied = itemTotal;
                    }
                    if (debug)
                        Debug.logInfo("tobeApplied:(" + tobeApplied + ") = " + "itemTotal(" + itemTotal
                                + ") - alreadyApplied(" + alreadyApplied
                                + ") but not more then (nonapplied) paymentAmount(" + paymentApplyAvailable
                                + ")", module);

                    if (tobeApplied.signum() == 0) {
                        // invoiceItem already fully applied so look at the next one....
                        continue;
                    }

                    if (paymentApplyAvailable.compareTo(tobeApplied) > 0) {
                        paymentApplyAvailable = paymentApplyAvailable.subtract(tobeApplied);
                    } else {
                        tobeApplied = paymentApplyAvailable;
                        paymentApplyAvailable = ZERO;
                    }

                    // create application payment record but check currency
                    // first if supplied
                    if (invoice.get("currencyUomId") != null && currencyUomId != null
                            && !invoice.getString("currencyUomId").equals(currencyUomId)) {
                        errorMessageList.add("Payment currency (" + currencyUomId + ") and invoice currency("
                                + invoice.getString("currencyUomId") + ") not the same\n");
                    } else {
                        paymentApplication.set("paymentApplicationId", null);
                        // make sure we get a new record
                        paymentApplication.set("invoiceId", invoiceId);
                        paymentApplication.set("invoiceItemSeqId",
                                currentInvoiceItem.getString("invoiceItemSeqId"));
                        paymentApplication.set("paymentId", paymentId);
                        paymentApplication.set("toPaymentId", toPaymentId);
                        paymentApplication.set("amountApplied", tobeApplied);
                        paymentApplication.set("billingAccountId", billingAccountId);
                        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
                        storePaymentApplication(delegator, paymentApplication, locale);
                    }

                }

                if (errorMessageList.size() > 0) {
                    return ServiceUtil.returnError(errorMessageList);
                } else {
                    if (successMessage != null) {
                        return ServiceUtil.returnSuccess(successMessage);
                    } else {
                        return ServiceUtil.returnSuccess();
                    }
                }
            }
        }
    }

    // if no paymentApplicationId supplied create a new record with the data
    // supplied...
    if (paymentApplicationId == null && amountApplied != null) {
        paymentApplication.set("paymentApplicationId", paymentApplicationId);
        paymentApplication.set("invoiceId", invoiceId);
        paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId);
        paymentApplication.set("paymentId", paymentId);
        paymentApplication.set("toPaymentId", toPaymentId);
        paymentApplication.set("amountApplied", amountApplied);
        paymentApplication.set("billingAccountId", billingAccountId);
        paymentApplication.set("taxAuthGeoId", taxAuthGeoId);
        return storePaymentApplication(delegator, paymentApplication, locale);
    }

    // should never come here...
    errorMessageList.add(
            UtilProperties.getMessage(resource, "AccountingPaymentApplicationParameterUnsuitable", locale));
    errorMessageList
            .add(UtilProperties.getMessage(resource, "AccountingPaymentApplicationParameterListUnsuitable",
                    UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId, "paymentId",
                            paymentId, "toPaymentId", toPaymentId, "paymentApplicationId", paymentApplicationId,
                            "amountApplied", amountApplied),
                    locale));
    return ServiceUtil.returnError(errorMessageList);
}

From source file:org.openbravo.test.costing.TestCosting.java

private ShipmentInOut createReturnMaterialReceipt(String returnFromCustomerId, BigDecimal price,
        BigDecimal quantity, String locatorId, int day) {
    try {//ww w.  j  a v a  2s.c  om
        Order returnFromCustomer = OBDal.getInstance().get(Order.class, returnFromCustomerId);
        ShipmentInOut returnMaterialReceipt = cloneMovement(
                returnFromCustomer.getOrderLineList().get(0).getProduct().getId(), true, quantity, locatorId,
                day);

        returnMaterialReceipt
                .setDocumentType(OBDal.getInstance().get(DocumentType.class, RFCRECEIPT_DOCUMENTTYPE_ID));
        returnMaterialReceipt.setDocumentNo(
                getDocumentNo(returnMaterialReceipt.getDocumentType().getDocumentSequence().getId()));

        returnMaterialReceipt.getMaterialMgmtShipmentInOutLineList().get(0)
                .setMovementQuantity(quantity.negate());
        returnMaterialReceipt.getMaterialMgmtShipmentInOutLineList().get(0)
                .setSalesOrderLine(returnFromCustomer.getOrderLineList().get(0));

        OBDal.getInstance().save(returnMaterialReceipt);
        OBDal.getInstance().flush();
        OBDal.getInstance().refresh(returnMaterialReceipt);

        return returnMaterialReceipt;
    } catch (Exception e) {
        throw new OBException(e);
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

private InventoryAmountUpdate createInventoryAmountUpdate(Product product, BigDecimal originalPrice,
        BigDecimal finalPrice, BigDecimal quantity, int day) {
    try {//ww  w .  ja v  a  2 s  . c  o m
        InventoryAmountUpdate inventoryAmountUpdate = createInventoryAmountUpdate(product.getId(),
                originalPrice, finalPrice, quantity, day);
        processInventoryAmountUpdate(inventoryAmountUpdate.getId());
        runCostingBackground();

        List<InventoryCount> inventoryCountList = getPhysicalInventory(inventoryAmountUpdate.getId());
        assertPhysicalInventory(inventoryCountList,
                new PhysicalInventoryAssert(product, finalPrice, quantity, day));

        postDocument(inventoryCountList.get(0));
        List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList1.add(
                new DocumentPostAssert("35000", amount0, quantity.multiply(originalPrice), quantity.negate()));
        documentPostAssertList1.add(
                new DocumentPostAssert("61000", quantity.multiply(originalPrice), amount0, quantity.negate()));
        assertDocumentPost(inventoryCountList.get(0), product.getId(), documentPostAssertList1);
        postDocument(inventoryCountList.get(1));
        List<DocumentPostAssert> documentPostAssertList2 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList2
                .add(new DocumentPostAssert("35000", quantity.multiply(finalPrice), amount0, quantity));
        documentPostAssertList2
                .add(new DocumentPostAssert("61000", amount0, quantity.multiply(finalPrice), quantity));
        assertDocumentPost(inventoryCountList.get(1), product.getId(), documentPostAssertList2);
        return inventoryAmountUpdate;
    } catch (Exception e) {
        throw new OBException(e);
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

private ShipmentInOut createReturnMaterialReceipt(Order returnFromCustomer, BigDecimal price,
        BigDecimal quantity, int day) {
    try {/*  w w w .ja v  a 2s.c  o m*/
        ShipmentInOut returnMaterialReceipt = createReturnMaterialReceipt(returnFromCustomer.getId(), price,
                quantity, LOCATOR1_ID, day);
        String productId = returnMaterialReceipt.getMaterialMgmtShipmentInOutLineList().get(0).getProduct()
                .getId();

        completeDocument(returnMaterialReceipt);
        runCostingBackground();
        ShipmentInOut returnReceipt = OBDal.getInstance().get(ShipmentInOut.class,
                returnMaterialReceipt.getId());
        postDocument(returnReceipt);
        returnReceipt = OBDal.getInstance().get(ShipmentInOut.class, returnMaterialReceipt.getId());
        List<DocumentPostAssert> documentPostAssertList = new ArrayList<DocumentPostAssert>();
        documentPostAssertList
                .add(new DocumentPostAssert("99900", amount0, quantity.multiply(price), quantity.negate()));
        documentPostAssertList
                .add(new DocumentPostAssert("35000", quantity.multiply(price), amount0, quantity.negate()));
        assertDocumentPost(returnReceipt, productId, documentPostAssertList);
        return returnReceipt;
    } catch (Exception e) {
        throw new OBException(e);
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

private Order createReturnFromCustomer(String goodsShipmentId, BigDecimal price, BigDecimal quantity, int day) {
    try {//  w  w  w  .jav a  2  s .  c o m
        ShipmentInOut goodsShipment = OBDal.getInstance().get(ShipmentInOut.class, goodsShipmentId);

        Order order = goodsShipment.getMaterialMgmtShipmentInOutLineList().get(0).getSalesOrderLine()
                .getSalesOrder();
        order.getOrderLineList().get(0).setGoodsShipmentLine(null);

        OBDal.getInstance().save(order);
        OBDal.getInstance().flush();
        OBDal.getInstance().refresh(order);

        Order returnFromCustomer = cloneOrder(
                goodsShipment.getMaterialMgmtShipmentInOutLineList().get(0).getProduct().getId(), true, price,
                quantity, day);

        returnFromCustomer
                .setDocumentType(OBDal.getInstance().get(DocumentType.class, RFCORDER_DOCUMENTTYPE_ID));
        returnFromCustomer
                .setTransactionDocument(OBDal.getInstance().get(DocumentType.class, RFCORDER_DOCUMENTTYPE_ID));
        returnFromCustomer.setDocumentNo(
                getDocumentNo(returnFromCustomer.getDocumentType().getDocumentSequence().getId()));
        returnFromCustomer.setSummedLineAmount(price.multiply(quantity.negate()));
        returnFromCustomer.setGrandTotalAmount(price.multiply(quantity.negate()));

        returnFromCustomer.getOrderLineList().get(0).setOrderedQuantity(quantity.negate());
        returnFromCustomer.getOrderLineList().get(0).setReservedQuantity(quantity.negate());
        returnFromCustomer.getOrderLineList().get(0).setLineNetAmount(price.multiply(quantity.negate()));
        returnFromCustomer.getOrderLineList().get(0)
                .setGoodsShipmentLine(goodsShipment.getMaterialMgmtShipmentInOutLineList().get(0));

        OBDal.getInstance().save(returnFromCustomer);
        OBDal.getInstance().flush();
        OBDal.getInstance().refresh(returnFromCustomer);

        return returnFromCustomer;
    } catch (Exception e) {
        throw new OBException(e);
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

@Test
public void testCostingV911() throws Exception {

    final int day0 = 0;
    final int day1 = 5;
    final int day2 = 10;
    final int day3 = 15;
    final BigDecimal price1 = new BigDecimal("15.00");
    final BigDecimal price2 = new BigDecimal("25.00");
    final BigDecimal price3 = new BigDecimal("35.00");
    final BigDecimal quantity1 = new BigDecimal("500");
    final BigDecimal quantity2 = new BigDecimal("400");
    final BigDecimal quantity3 = new BigDecimal("200");
    final BigDecimal quantity4 = new BigDecimal("300");
    final String costType = "AVA";

    try {//from  w  w  w .  ja  v  a 2 s .c  o  m

        OBContext.setOBContext(USER_ID, ROLE_ID, CLIENT_ID, ORGANIZATION_ID);
        OBContext.setAdminMode(true);

        // Create a new product for the test
        Product product = createProduct(price1, price2, costType);

        // Create purchase invoice, post it and assert it
        Invoice purchaseInvoice = createPurchaseInvoice(product, price1, quantity1, day0);

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment = createGoodsShipment(product, price2, quantity2, day1);

        // Create goods receipt, run costing background, post it and assert it
        ShipmentInOut goodsReceipt1 = createGoodsReceipt(purchaseInvoice, price2, quantity3, day2);

        // Create goods receipt, run costing background, post it and assert it
        ShipmentInOut goodsReceipt2 = createGoodsReceipt(purchaseInvoice, price1, quantity4, day3);

        // Assert product transactions
        List<ProductTransactionAssert> productTransactionAssertList = new ArrayList<ProductTransactionAssert>();
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsShipment.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price2, price2));
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsReceipt1.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price2, price3, price1));
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsReceipt2.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price1, price1));
        assertProductTransaction(product.getId(), productTransactionAssertList);

        // Assert product costing
        List<MaterialTransaction> transactionList = getProductTransactions(product.getId());
        List<ProductCostingAssert> productCostingAssertList = new ArrayList<ProductCostingAssert>();
        productCostingAssertList.add(new ProductCostingAssert(null, null, null, price2, null, costType));
        productCostingAssertList.add(new ProductCostingAssert(transactionList.get(1), price1, price2, price1,
                quantity2.negate().add(quantity3)));
        productCostingAssertList.add(new ProductCostingAssert(transactionList.get(2), price1, null, price1,
                quantity2.negate().add(quantity3).add(quantity4)));
        assertProductCosting(product.getId(), productCostingAssertList);

        // Assert cost adjustment
        List<CostAdjustment> costAdjustmentList = getCostAdjustment(product.getId());
        List<List<CostAdjustmentAssert>> costAdjustmentAssertList = new ArrayList<List<CostAdjustmentAssert>>();
        List<CostAdjustmentAssert> costAdjustmentAssertLineList1 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(1), "PDC",
                quantity3.multiply(price1).add(quantity3.multiply(price2).negate()), day0, true));
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(1), "NSC",
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), day2, false, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList1);
        List<CostAdjustmentAssert> costAdjustmentAssertLineList2 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList2
                .add(new CostAdjustmentAssert(transactionList.get(2), "NSC", amount0, day3, true, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList2);
        assertCostAdjustment(costAdjustmentList, costAdjustmentAssertList);

        // Post cost adjustment 1 and assert it
        postDocument(costAdjustmentList.get(0));
        List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList1.add(new DocumentPostAssert("99904",
                quantity3.multiply(price2).add(quantity3.multiply(price1).negate()), amount0, null));
        documentPostAssertList1.add(new DocumentPostAssert("35000", amount0,
                quantity3.multiply(price2).add(quantity3.multiply(price1).negate()), null));
        documentPostAssertList1.add(new DocumentPostAssert("61000", amount0,
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), null));
        documentPostAssertList1.add(new DocumentPostAssert("35000",
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), amount0, null));
        CostAdjustment costAdjustment1 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(0).getId());
        assertDocumentPost(costAdjustment1, product.getId(), documentPostAssertList1);

        OBDal.getInstance().commitAndClose();

    } catch (Exception e) {
        System.out.println(e.getMessage());
        throw new OBException(e);
    }

    finally {
        OBContext.restorePreviousMode();
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

@Test
public void testCostingMCC1() throws Exception {

    final int day0 = 0;
    final int day1 = 5;
    final int day2 = 10;
    final int day3 = 15;
    final int day4 = 20;
    final int day5 = 25;
    final BigDecimal price1 = new BigDecimal("11.50");
    final BigDecimal price2 = new BigDecimal("15.00");
    final BigDecimal price3 = new BigDecimal("15.0714");
    final BigDecimal price4 = new BigDecimal("14.9375");
    final BigDecimal price5 = new BigDecimal("11.4375");
    final BigDecimal quantity1 = new BigDecimal("15");
    final BigDecimal quantity2 = new BigDecimal("7");
    final BigDecimal quantity3 = new BigDecimal("3");
    final BigDecimal amount1 = new BigDecimal("0.50");

    try {/*from  ww  w.  j  a  va2s  .c o  m*/

        OBContext.setOBContext(USER_ID, ROLE_ID, CLIENT_ID, ORGANIZATION_ID);
        OBContext.setAdminMode(true);

        // Create a new product for the test
        Product product = createProduct(price1);

        // Create purchase order and book it
        Order purchaseOrder = createPurchaseOrder(product, price1, quantity1, day1);

        // Create goods receipt, run costing background, post it and assert it
        ShipmentInOut goodsReceipt = createGoodsReceipt(purchaseOrder, price1, quantity1, day0);

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment1 = createGoodsShipment(product, price1, quantity2, day2);

        // Update transaction total cost amount
        manualCostAdjustment(getProductTransactions(product.getId()).get(1), amount1, true, false, day3);

        // Create purchase invoice, post it and assert it
        createPurchaseInvoice(goodsReceipt, price2, quantity1, day4);

        // Run price correction background
        runPriceBackground();

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment2 = createGoodsShipment(product, price4, quantity3, day5);

        // Assert product transactions
        List<ProductTransactionAssert> productTransactionAssertList = new ArrayList<ProductTransactionAssert>();
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsReceipt.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price1, price2));
        productTransactionAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
                .get(ShipmentInOut.class, goodsShipment1.getId()).getMaterialMgmtShipmentInOutLineList().get(0),
                price1, price3, price2));
        productTransactionAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
                .get(ShipmentInOut.class, goodsShipment2.getId()).getMaterialMgmtShipmentInOutLineList().get(0),
                price4, price4));
        assertProductTransaction(product.getId(), productTransactionAssertList);

        // Assert product costing
        List<MaterialTransaction> transactionList = getProductTransactions(product.getId());
        List<ProductCostingAssert> productCostingAssertList = new ArrayList<ProductCostingAssert>();
        productCostingAssertList
                .add(new ProductCostingAssert(transactionList.get(0), price2, price1, price2, quantity1));
        productCostingAssertList.add(new ProductCostingAssert(transactionList.get(1), price2, price5, price4,
                quantity1.add(quantity2.negate())));
        assertProductCosting(product.getId(), productCostingAssertList);

        // Assert cost adjustment
        List<CostAdjustment> costAdjustmentList = getCostAdjustment(product.getId());
        List<List<CostAdjustmentAssert>> costAdjustmentAssertList = new ArrayList<List<CostAdjustmentAssert>>();
        List<CostAdjustmentAssert> costAdjustmentAssertLineList1 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList1
                .add(new CostAdjustmentAssert(transactionList.get(1), "MCC", amount1, day3, true, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList1);
        List<CostAdjustmentAssert> costAdjustmentAssertLineList2 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList2.add(new CostAdjustmentAssert(transactionList.get(0), "PDC",
                quantity1.multiply(price2).add(quantity1.multiply(price1).negate()), day4, true));
        costAdjustmentAssertLineList2.add(new CostAdjustmentAssert(transactionList.get(1), "PDC",
                quantity2.multiply(price2).add(quantity2.multiply(price1).negate()), day4, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList2);
        assertCostAdjustment(costAdjustmentList, costAdjustmentAssertList);

        // Post cost adjustment 1 and assert it
        postDocument(costAdjustmentList.get(0));
        List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList1.add(new DocumentPostAssert("99900", amount1, amount0, null));
        documentPostAssertList1.add(new DocumentPostAssert("35000", amount0, amount1, null));
        CostAdjustment costAdjustment1 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(0).getId());
        assertDocumentPost(costAdjustment1, product.getId(), documentPostAssertList1);

        // Post cost adjustment 1 and assert it
        postDocument(costAdjustmentList.get(1));
        List<DocumentPostAssert> documentPostAssertList2 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList2.add(new DocumentPostAssert("99904", amount0,
                quantity1.multiply(price2).add(quantity1.multiply(price1).negate()), null));
        documentPostAssertList2.add(new DocumentPostAssert("35000",
                quantity1.multiply(price2).add(quantity1.multiply(price1).negate()), amount0, null));
        documentPostAssertList2.add(new DocumentPostAssert("99900",
                quantity2.multiply(price2).add(quantity2.multiply(price1).negate()), amount0, null));
        documentPostAssertList2.add(new DocumentPostAssert("35000", amount0,
                quantity2.multiply(price2).add(quantity2.multiply(price1).negate()), null));
        CostAdjustment costAdjustment2 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(1).getId());
        assertDocumentPost(costAdjustment2, product.getId(), documentPostAssertList2);

        OBDal.getInstance().commitAndClose();

    } catch (Exception e) {
        System.out.println(e.getMessage());
        throw new OBException(e);
    }

    finally {
        OBContext.restorePreviousMode();
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

@Test
public void testCostingR10() throws Exception {

    final int day0 = 0;
    final int day1 = 5;
    final int day2 = 10;
    final int day3 = 15;
    final int day4 = 20;
    final int day5 = 25;
    final BigDecimal price1 = new BigDecimal("15.00");
    final BigDecimal price2 = new BigDecimal("40.00");
    final BigDecimal price3 = new BigDecimal("9.00");
    final BigDecimal quantity1 = new BigDecimal("180");
    final BigDecimal quantity2 = new BigDecimal("80");
    final BigDecimal quantity3 = new BigDecimal("40");

    try {//from   www  .  j  a  v a  2  s.c o  m

        OBContext.setOBContext(USER_ID, ROLE_ID, CLIENT_ID, ORGANIZATION_ID);
        OBContext.setAdminMode(true);

        // Create a new product for the test
        Product product = createProduct(price1, price2);

        // Create purchase order and book it
        Order purchaseOrder = createPurchaseOrder(product, price1, quantity1, day0);

        // Create goods receipt, run costing background, post it and assert it
        ShipmentInOut goodsReceipt = createGoodsReceipt(purchaseOrder, price1, quantity1, day1);

        // Create purchase order and book it
        Order saleseOrder = createSalesOrder(product, price2, quantity2, day2);

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment = createGoodsShipment(saleseOrder, price1, quantity2, day3);

        // Update purchase order line product price
        updatePurchaseOrder(purchaseOrder, price3);

        // Run price correction background
        runPriceBackground();

        // Create purchase invoice, post it and assert it
        createPurchaseInvoice(goodsReceipt, price3, quantity1, day5);

        // Run price correction background
        runPriceBackground();

        // Create return from customer, run costing background, post it and assert it
        Order returnFromCustomer = createReturnFromCustomer(goodsShipment, price2, quantity3, day3);

        // Create return material receipt, run costing background, post it and assert it
        ShipmentInOut returnMaterialReceipt = createReturnMaterialReceipt(returnFromCustomer, price3, quantity3,
                day4);

        // Assert product transactions
        List<ProductTransactionAssert> productTransactionAssertList = new ArrayList<ProductTransactionAssert>();
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsReceipt.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price1, price3));
        productTransactionAssertList.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsShipment.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price1, price3));
        productTransactionAssertList.add(new ProductTransactionAssert(
                OBDal.getInstance().get(ShipmentInOut.class, returnMaterialReceipt.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0),
                price3, price3));
        assertProductTransaction(product.getId(), productTransactionAssertList);

        // Assert product costing
        List<MaterialTransaction> transactionList = getProductTransactions(product.getId());
        List<ProductCostingAssert> productCostingAssertList = new ArrayList<ProductCostingAssert>();
        productCostingAssertList
                .add(new ProductCostingAssert(transactionList.get(0), price3, price1, price3, quantity1));
        productCostingAssertList.add(new ProductCostingAssert(transactionList.get(2), price3, null, price3,
                quantity1.add(quantity2.negate()).add(quantity3)));
        assertProductCosting(product.getId(), productCostingAssertList);

        // Assert cost adjustment
        List<CostAdjustment> costAdjustmentList = getCostAdjustment(product.getId());
        List<List<CostAdjustmentAssert>> costAdjustmentAssertList = new ArrayList<List<CostAdjustmentAssert>>();
        List<CostAdjustmentAssert> costAdjustmentAssertLineList1 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(0), "PDC",
                quantity1.multiply(price3).add(quantity1.multiply(price1).negate()), day1, true));
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(1), "PDC",
                quantity2.multiply(price3).add(quantity2.multiply(price1).negate()), day3, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList1);
        ;
        assertCostAdjustment(costAdjustmentList, costAdjustmentAssertList);

        // Post cost adjustment and assert it
        postDocument(costAdjustmentList.get(0));
        List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList1.add(new DocumentPostAssert("99904",
                quantity1.multiply(price1).add(quantity1.multiply(price3).negate()), amount0, null));
        documentPostAssertList1.add(new DocumentPostAssert("35000", amount0,
                quantity1.multiply(price1).add(quantity1.multiply(price3).negate()), null));
        documentPostAssertList1.add(new DocumentPostAssert("99900", amount0,
                quantity2.multiply(price1).add(quantity2.multiply(price3).negate()), null));
        documentPostAssertList1.add(new DocumentPostAssert("35000",
                quantity2.multiply(price1).add(quantity2.multiply(price3).negate()), amount0, null));
        CostAdjustment costAdjustment1 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(0).getId());
        assertDocumentPost(costAdjustment1, product.getId(), documentPostAssertList1);

        OBDal.getInstance().commitAndClose();

    } catch (Exception e) {
        System.out.println(e.getMessage());
        throw new OBException(e);
    }

    finally {
        OBContext.restorePreviousMode();
    }
}

From source file:org.openbravo.test.costing.TestCosting.java

@Test
public void testCostingLC9() throws Exception {

    final int day0 = 0;
    final int day1 = 5;
    final int day2 = 10;
    final int day3 = 15;
    final int day4 = 20;
    final int day5 = 25;
    final int day6 = 30;
    final BigDecimal price1 = new BigDecimal("120.00");
    final BigDecimal price2 = new BigDecimal("210.00");
    final BigDecimal price3 = new BigDecimal("120.21");
    final BigDecimal price4 = new BigDecimal("150.00");
    final BigDecimal price5 = new BigDecimal("120.30");
    final BigDecimal price6 = new BigDecimal("120.3250");
    final BigDecimal price7 = new BigDecimal("120.2938");
    final BigDecimal quantity1 = new BigDecimal("1000");
    final BigDecimal quantity2 = BigDecimal.ONE;
    final BigDecimal quantity3 = new BigDecimal("200");
    final BigDecimal quantity4 = new BigDecimal("2");
    final BigDecimal amount1 = new BigDecimal("5.00");

    try {/*from   w w  w . j av a2 s. c  o  m*/

        OBContext.setOBContext(USER_ID, ROLE_ID, CLIENT_ID, ORGANIZATION_ID);
        OBContext.setAdminMode(true);

        // Create a new product for the test
        Product product = createProduct(price1);

        // Create purchase order and book it
        Order purchaseOrder = createPurchaseOrder(product, price1, quantity1, day0);

        // Create goods receipt, run costing background, post it and assert it
        ShipmentInOut goodsReceipt = createGoodsReceipt(purchaseOrder, price1, quantity1, day1);

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment1 = createGoodsShipment(product, price1, quantity3, day2);

        // Create Landed Cost
        List<String> landedCostTypeIdList = new ArrayList<String>();
        landedCostTypeIdList.add(LANDEDCOSTTYPE2_ID);
        List<BigDecimal> amountList = new ArrayList<BigDecimal>();
        amountList.add(quantity2.multiply(price2));
        List<ShipmentInOut> receiptList = new ArrayList<ShipmentInOut>();
        receiptList.add(goodsReceipt);
        LandedCost landedCost = createLandedCost(landedCostTypeIdList, amountList, receiptList, null, day3);

        // Create goods shipment, run costing background, post it and assert it
        ShipmentInOut goodsShipment2 = createGoodsShipment(product, price3, quantity3, day4);

        // Create purchase invoice with landed cost, post it and assert it
        Invoice purchaseInvoiceLandedCost = createPurchaseInvoiceLandedCost(LANDEDCOSTTYPE2_ID, price4,
                quantity4, day5);

        // Match invoice landed cost
        matchInvoiceLandedCost(purchaseInvoiceLandedCost.getInvoiceLineList().get(0),
                landedCost.getLandedCostCostList().get(0), true);

        // Post landed cost cost and assert it
        postLandedCostLine(landedCost.getLandedCostCostList().get(0),
                purchaseInvoiceLandedCost.getInvoiceLineList().get(0));

        // Update transaction total cost amount
        manualCostAdjustment(getProductTransactions(product.getId()).get(1), amount1, true, true, day6);

        // Assert product transactions
        List<ProductTransactionAssert> productTransactionAssertList1 = new ArrayList<ProductTransactionAssert>();
        productTransactionAssertList1.add(
                new ProductTransactionAssert(OBDal.getInstance().get(ShipmentInOut.class, goodsReceipt.getId())
                        .getMaterialMgmtShipmentInOutLineList().get(0), price1, price5, price1));
        productTransactionAssertList1.add(new ProductTransactionAssert(OBDal.getInstance()
                .get(ShipmentInOut.class, goodsShipment1.getId()).getMaterialMgmtShipmentInOutLineList().get(0),
                price1, price6));
        productTransactionAssertList1.add(new ProductTransactionAssert(OBDal.getInstance()
                .get(ShipmentInOut.class, goodsShipment2.getId()).getMaterialMgmtShipmentInOutLineList().get(0),
                price3, price7));
        assertProductTransaction(product.getId(), productTransactionAssertList1);

        // Assert product costing
        List<MaterialTransaction> transactionList = getProductTransactions(product.getId());
        List<ProductCostingAssert> productCostingAssertList1 = new ArrayList<ProductCostingAssert>();
        productCostingAssertList1
                .add(new ProductCostingAssert(transactionList.get(0), price1, price1, price5, quantity1));
        productCostingAssertList1.add(new ProductCostingAssert(transactionList.get(1), price7, null, price7,
                quantity1.add(quantity3.negate())));
        assertProductCosting(product.getId(), productCostingAssertList1);

        // Assert cost adjustment
        List<CostAdjustment> costAdjustmentList = getCostAdjustment(product.getId());
        List<List<CostAdjustmentAssert>> costAdjustmentAssertList = new ArrayList<List<CostAdjustmentAssert>>();
        List<CostAdjustmentAssert> costAdjustmentAssertLineList1 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(0), "LC",
                quantity2.multiply(price2), day3, true, false));
        costAdjustmentAssertLineList1.add(new CostAdjustmentAssert(transactionList.get(1), "PDC",
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), day3, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList1);
        List<CostAdjustmentAssert> costAdjustmentAssertLineList2 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList2.add(new CostAdjustmentAssert(transactionList.get(0), "LC",
                quantity4.multiply(price4).add(quantity2.multiply(price2).negate()), day3, true, false));
        costAdjustmentAssertLineList2.add(new CostAdjustmentAssert(transactionList.get(1), "PDC",
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), day3, false));
        costAdjustmentAssertLineList2.add(new CostAdjustmentAssert(transactionList.get(2), "PDC",
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), day4, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList2);
        List<CostAdjustmentAssert> costAdjustmentAssertLineList3 = new ArrayList<CostAdjustmentAssert>();
        costAdjustmentAssertLineList3
                .add(new CostAdjustmentAssert(transactionList.get(1), "MCC", amount1, day6, true));
        costAdjustmentAssertLineList3.add(new CostAdjustmentAssert(transactionList.get(2), "PDC",
                quantity3.multiply(price7).add(quantity3.multiply(price5).negate()), day6, false));
        costAdjustmentAssertList.add(costAdjustmentAssertLineList3);
        assertCostAdjustment(costAdjustmentList, costAdjustmentAssertList);

        // Post cost adjustment and assert it
        postDocument(costAdjustmentList.get(0));
        List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList1.add(new DocumentPostAssert("99900",
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), amount0, null));
        documentPostAssertList1.add(new DocumentPostAssert("35000", amount0,
                quantity3.multiply(price3).add(quantity3.multiply(price1).negate()), null));
        CostAdjustment costAdjustment1 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(0).getId());
        assertDocumentPost(costAdjustment1, product.getId(), documentPostAssertList1);

        // Post cost adjustment and assert it
        postDocument(costAdjustmentList.get(1));
        List<DocumentPostAssert> documentPostAssertList2 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList2.add(new DocumentPostAssert("99900",
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), amount0, null));
        documentPostAssertList2.add(new DocumentPostAssert("35000", amount0,
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), null));
        documentPostAssertList2.add(new DocumentPostAssert("99900",
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), amount0, null));
        documentPostAssertList2.add(new DocumentPostAssert("35000", amount0,
                quantity3.multiply(price5).add(quantity3.multiply(price3).negate()), null));
        CostAdjustment costAdjustment2 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(1).getId());
        assertDocumentPost(costAdjustment2, product.getId(), documentPostAssertList2);

        // Post cost adjustment and assert it
        postDocument(costAdjustmentList.get(2));
        List<DocumentPostAssert> documentPostAssertList3 = new ArrayList<DocumentPostAssert>();
        documentPostAssertList3.add(new DocumentPostAssert("99900", amount1, amount0, null));
        documentPostAssertList3.add(new DocumentPostAssert("35000", amount0, amount1, null));
        documentPostAssertList3.add(new DocumentPostAssert("99900", amount0,
                quantity3.multiply(price5).add(quantity3.multiply(price7).negate()), null));
        documentPostAssertList3.add(new DocumentPostAssert("35000",
                quantity3.multiply(price5).add(quantity3.multiply(price7).negate()), amount0, null));
        CostAdjustment costAdjustment3 = OBDal.getInstance().get(CostAdjustment.class,
                costAdjustmentList.get(2).getId());
        assertDocumentPost(costAdjustment3, product.getId(), documentPostAssertList3);

        OBDal.getInstance().commitAndClose();

    } catch (Exception e) {
        System.out.println(e.getMessage());
        throw new OBException(e);
    }

    finally {
        OBContext.restorePreviousMode();
    }
}