Example usage for java.math BigDecimal compareTo

List of usage examples for java.math BigDecimal compareTo

Introduction

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

Prototype

@Override
public int compareTo(BigDecimal val) 

Source Link

Document

Compares this BigDecimal with the specified BigDecimal .

Usage

From source file:com.gst.portfolio.loanaccount.domain.Loan.java

public void regenerateScheduleOnDisbursement(final ScheduleGeneratorDTO scheduleGeneratorDTO,
        final boolean recalculateSchedule, final LocalDate actualDisbursementDate, BigDecimal emiAmount,
        final AppUser currentUser, LocalDate nextPossibleRepaymentDate, Date rescheduledRepaymentDate) {
    boolean isEmiAmountChanged = false;
    if ((this.loanProduct.isMultiDisburseLoan() || this.loanProduct.canDefineInstallmentAmount())
            && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) {
        if (this.loanProduct.isMultiDisburseLoan()) {
            final Date dateValue = null;
            final boolean isSpecificToInstallment = false;
            final Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled = scheduleGeneratorDTO
                    .isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled();
            Date effectiveDateFrom = actualDisbursementDate.toDate();
            if (!isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled
                    && actualDisbursementDate.equals(nextPossibleRepaymentDate)) {
                effectiveDateFrom = nextPossibleRepaymentDate.plusDays(1).toDate();
            }/*from  ww  w  .  j  a v  a 2s  .  c  o  m*/
            LoanTermVariations loanVariationTerms = new LoanTermVariations(
                    LoanTermVariationType.EMI_AMOUNT.getValue(), effectiveDateFrom, emiAmount, dateValue,
                    isSpecificToInstallment, this, LoanStatus.ACTIVE.getValue());
            this.loanTermVariations.add(loanVariationTerms);
        } else {
            this.fixedEmiAmount = emiAmount;
        }
        isEmiAmountChanged = true;
    }
    if (rescheduledRepaymentDate != null && this.loanProduct.isMultiDisburseLoan()) {
        final boolean isSpecificToInstallment = false;
        LoanTermVariations loanVariationTerms = new LoanTermVariations(
                LoanTermVariationType.DUE_DATE.getValue(), nextPossibleRepaymentDate.toDate(), emiAmount,
                rescheduledRepaymentDate, isSpecificToInstallment, this, LoanStatus.ACTIVE.getValue());
        this.loanTermVariations.add(loanVariationTerms);
    }

    if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule
            || isEmiAmountChanged || rescheduledRepaymentDate != null) {
        if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
        } else {
            regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
        }
    }
}

From source file:com.gst.portfolio.loanaccount.domain.Loan.java

public Map<String, Object> loanApplicationApproval(final AppUser currentUser, final JsonCommand command,
        final JsonArray disbursementDataArray, final LoanLifecycleStateMachine loanLifecycleStateMachine) {

    validateAccountStatus(LoanEvent.LOAN_APPROVED);

    final Map<String, Object> actualChanges = new LinkedHashMap<>();

    /*/*w w w . j a va  2 s.  c  om*/
     * statusEnum is holding the possible new status derived from
     * loanLifecycleStateMachine.transition.
     */

    final LoanStatus newStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED,
            LoanStatus.fromInt(this.loanStatus));

    /*
     * FIXME: There is no need to check below condition, if
     * loanLifecycleStateMachine.transition is doing it's responsibility
     * properly. Better implementation approach is, if code passes invalid
     * combination of states (fromState and toState), state machine should
     * return invalidate state and below if condition should check for not
     * equal to invalidateState, instead of check new value is same as
     * present value.
     */

    if (!newStatusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
        this.loanStatus = newStatusEnum.getValue();
        actualChanges.put("status", LoanEnumerations.status(this.loanStatus));

        // only do below if status has changed in the 'approval' case
        LocalDate approvedOn = command.localDateValueOfParameterNamed("approvedOnDate");
        String approvedOnDateChange = command.stringValueOfParameterNamed("approvedOnDate");
        if (approvedOn == null) {
            approvedOn = command.localDateValueOfParameterNamed("eventDate");
            approvedOnDateChange = command.stringValueOfParameterNamed("eventDate");
        }

        LocalDate expecteddisbursementDate = command.localDateValueOfParameterNamed("expectedDisbursementDate");

        BigDecimal approvedLoanAmount = command
                .bigDecimalValueOfParameterNamed(LoanApiConstants.approvedLoanAmountParameterName);

        if (approvedLoanAmount != null) {

            // Approved amount has to be less than or equal to principal
            // amount demanded

            if (approvedLoanAmount.compareTo(this.proposedPrincipal) == -1) {

                this.approvedPrincipal = approvedLoanAmount;

                /*
                 * All the calculations are done based on the principal
                 * amount, so it is necessary to set principal amount to
                 * approved amount
                 */

                this.loanRepaymentScheduleDetail.setPrincipal(approvedLoanAmount);

                actualChanges.put(LoanApiConstants.approvedLoanAmountParameterName, approvedLoanAmount);
                actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName, approvedLoanAmount);
            } else if (approvedLoanAmount.compareTo(this.proposedPrincipal) == 1) {
                final String errorMessage = "Loan approved amount can't be greater than loan amount demanded.";
                throw new InvalidLoanStateTransitionException("approval",
                        "amount.can't.be.greater.than.loan.amount.demanded", errorMessage,
                        this.proposedPrincipal, approvedLoanAmount);
            }

            /* Update disbursement details */
            if (disbursementDataArray != null) {
                updateDisbursementDetails(command, actualChanges);
            }
        }
        if (loanProduct.isMultiDisburseLoan()) {
            recalculateAllCharges();

            if (this.disbursementDetails.isEmpty()) {
                final String errorMessage = "For this loan product, disbursement details must be provided";
                throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName,
                        errorMessage);
            }

            if (this.disbursementDetails.size() > loanProduct.maxTrancheCount()) {
                final String errorMessage = "Number of tranche shouldn't be greter than "
                        + loanProduct.maxTrancheCount();
                throw new ExceedingTrancheCountException(LoanApiConstants.disbursementDataParameterName,
                        errorMessage, loanProduct.maxTrancheCount(), disbursementDetails.size());
            }
        }
        this.approvedOnDate = approvedOn.toDate();
        this.approvedBy = currentUser;
        actualChanges.put("locale", command.locale());
        actualChanges.put("dateFormat", command.dateFormat());
        actualChanges.put("approvedOnDate", approvedOnDateChange);

        final LocalDate submittalDate = new LocalDate(this.submittedOnDate);
        if (approvedOn.isBefore(submittalDate)) {
            final String errorMessage = "The date on which a loan is approved cannot be before its submittal date: "
                    + submittalDate.toString();
            throw new InvalidLoanStateTransitionException("approval", "cannot.be.before.submittal.date",
                    errorMessage, getApprovedOnDate(), submittalDate);
        }

        if (expecteddisbursementDate != null) {
            this.expectedDisbursementDate = expecteddisbursementDate.toDate();
            actualChanges.put("expectedDisbursementDate", expectedDisbursementDate);

            if (expecteddisbursementDate.isBefore(approvedOn)) {
                final String errorMessage = "The expected disbursement date should be either on or after the approval date: "
                        + approvedOn.toString();
                throw new InvalidLoanStateTransitionException("expecteddisbursal",
                        "should.be.on.or.after.approval.date", errorMessage, getApprovedOnDate(),
                        expecteddisbursementDate);
            }
        }

        validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_APPROVED, approvedOn);

        if (approvedOn.isAfter(DateUtils.getLocalDateOfTenant())) {
            final String errorMessage = "The date on which a loan is approved cannot be in the future.";
            throw new InvalidLoanStateTransitionException("approval", "cannot.be.a.future.date", errorMessage,
                    getApprovedOnDate());
        }

        if (this.loanOfficer != null) {
            final LoanOfficerAssignmentHistory loanOfficerAssignmentHistory = LoanOfficerAssignmentHistory
                    .createNew(this, this.loanOfficer, approvedOn);
            this.loanOfficerHistory.add(loanOfficerAssignmentHistory);
        }
    }

    return actualChanges;
}

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

public static Map<String, Object> createInvoicesFromShipments(DispatchContext dctx,
        Map<String, ? extends Object> context) {
    Delegator delegator = dctx.getDelegator();
    LocalDispatcher dispatcher = dctx.getDispatcher();
    List<String> shipmentIds = UtilGenerics.checkList(context.get("shipmentIds"));
    Locale locale = (Locale) context.get("locale");
    Boolean createSalesInvoicesForDropShipments = (Boolean) context.get("createSalesInvoicesForDropShipments");
    if (UtilValidate.isEmpty(createSalesInvoicesForDropShipments))
        createSalesInvoicesForDropShipments = Boolean.FALSE;

    boolean salesShipmentFound = false;
    boolean purchaseShipmentFound = false;
    boolean dropShipmentFound = false;

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

    //DEJ20060520: not used? planned to be used? List shipmentIdList = new LinkedList();
    for (String tmpShipmentId : shipmentIds) {
        try {//  ww w  .jav  a  2 s . co m
            GenericValue shipment = EntityQuery.use(delegator).from("Shipment")
                    .where("shipmentId", tmpShipmentId).queryOne();
            if ((shipment.getString("shipmentTypeId") != null)
                    && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) {
                purchaseShipmentFound = true;
            } else if ((shipment.getString("shipmentTypeId") != null)
                    && (shipment.getString("shipmentTypeId").equals("DROP_SHIPMENT"))) {
                dropShipmentFound = true;
            } else {
                salesShipmentFound = true;
            }
            if (purchaseShipmentFound && salesShipmentFound && dropShipmentFound) {
                return ServiceUtil.returnError(UtilProperties.getMessage(
                        resource, "AccountingShipmentsOfDifferentTypes", UtilMisc.toMap("tmpShipmentId",
                                tmpShipmentId, "shipmentTypeId", shipment.getString("shipmentTypeId")),
                        locale));
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, "Trouble getting Shipment entity for shipment " + tmpShipmentId, module);
            return ServiceUtil
                    .returnError(UtilProperties.getMessage(resource, "AccountingTroubleGettingShipmentEntity",
                            UtilMisc.toMap("tmpShipmentId", tmpShipmentId), locale));
        }
    }
    EntityQuery shipmentQuery = EntityQuery.use(delegator)
            .where(EntityCondition.makeCondition("shipmentId", EntityOperator.IN, shipmentIds))
            .orderBy("shipmentId");
    // check the status of the shipment

    // get the items of the shipment.  They can come from ItemIssuance if the shipment were from a sales order, ShipmentReceipt
    // if it were a purchase order or from the order items of the (possibly linked) orders if the shipment is a drop shipment
    List<GenericValue> items = null;
    List<GenericValue> orderItemAssocs = null;
    try {
        if (purchaseShipmentFound) {
            items = shipmentQuery.from("ShipmentReceipt").queryList();
            // filter out items which have been received but are not actually owned by an internal organization, so they should not be on a purchase invoice
            Iterator<GenericValue> itemsIter = items.iterator();
            while (itemsIter.hasNext()) {
                GenericValue item = itemsIter.next();
                GenericValue inventoryItem = item.getRelatedOne("InventoryItem", false);
                GenericValue ownerPartyRole = EntityQuery.use(delegator).from("PartyRole").where("partyId",
                        inventoryItem.get("ownerPartyId"), "roleTypeId", "INTERNAL_ORGANIZATIO").cache()
                        .queryOne();
                if (UtilValidate.isEmpty(ownerPartyRole)) {
                    itemsIter.remove();
                }
            }
        } else if (dropShipmentFound) {

            List<GenericValue> shipments = shipmentQuery.from("Shipment").queryList();

            // Get the list of purchase order IDs related to the shipments
            List<String> purchaseOrderIds = EntityUtil.getFieldListFromEntityList(shipments, "primaryOrderId",
                    true);

            if (createSalesInvoicesForDropShipments) {

                // If a sales invoice is being created for a drop shipment, we have to reference the original sales order items
                // Get the list of the linked orderIds (original sales orders)
                orderItemAssocs = EntityQuery.use(delegator).from("OrderItemAssoc")
                        .where(EntityCondition.makeCondition("toOrderId", EntityOperator.IN, purchaseOrderIds))
                        .queryList();

                // Get only the order items which are indirectly related to the purchase order - this limits the list to the drop ship group(s)
                items = EntityUtil.getRelated("FromOrderItem", null, orderItemAssocs, false);
            } else {

                // If it's a purchase invoice being created, the order items for that purchase orders can be used directly
                items = EntityQuery.use(delegator).from("OrderItem")
                        .where(EntityCondition.makeCondition("orderId", EntityOperator.IN, purchaseOrderIds))
                        .queryList();
            }
        } else {
            items = shipmentQuery.from("ItemIssuance").queryList();
        }
    } catch (GenericEntityException e) {
        Debug.logError(e, "Problem getting issued items from shipments", module);
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingProblemGettingItemsFromShipments", locale));
    }
    if (items.size() == 0) {
        Debug.logInfo("No items issued for shipments", module);
        return ServiceUtil.returnSuccess();
    }

    // group items by order
    Map<String, List<GenericValue>> shippedOrderItems = new HashMap<String, List<GenericValue>>();
    for (GenericValue item : items) {
        String orderId = item.getString("orderId");
        String orderItemSeqId = item.getString("orderItemSeqId");
        List<GenericValue> itemsByOrder = shippedOrderItems.get(orderId);
        if (itemsByOrder == null) {
            itemsByOrder = new LinkedList<GenericValue>();
        }

        // check and make sure we haven't already billed for this issuance or shipment receipt
        List<EntityCondition> billFields = new LinkedList<EntityCondition>();
        billFields.add(EntityCondition.makeCondition("orderId", orderId));
        billFields.add(EntityCondition.makeCondition("orderItemSeqId", orderItemSeqId));
        billFields
                .add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "INVOICE_CANCELLED"));

        if (dropShipmentFound) {

            // Drop shipments have neither issuances nor receipts, so this check is meaningless
            itemsByOrder.add(item);
            shippedOrderItems.put(orderId, itemsByOrder);
            continue;
        } else if (item.getEntityName().equals("ItemIssuance")) {
            billFields.add(EntityCondition.makeCondition("itemIssuanceId", item.get("itemIssuanceId")));
        } else if (item.getEntityName().equals("ShipmentReceipt")) {
            billFields.add(EntityCondition.makeCondition("shipmentReceiptId", item.getString("receiptId")));
        }
        List<GenericValue> itemBillings = null;
        try {
            itemBillings = EntityQuery.use(delegator).from("OrderItemBillingAndInvoiceAndItem")
                    .where(billFields).queryList();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Problem looking up OrderItemBilling records for " + billFields, module);
            return ServiceUtil.returnError(
                    UtilProperties.getMessage(resource, "AccountingProblemLookingUpOrderItemBilling",
                            UtilMisc.toMap("billFields", billFields), locale));
        }

        // if none found, then okay to bill
        if (itemBillings.size() == 0) {
            itemsByOrder.add(item);
        }

        // update the map with modified list
        shippedOrderItems.put(orderId, itemsByOrder);
    }

    // make sure we aren't billing items already invoiced i.e. items billed as digital (FINDIG)
    Set<String> orders = shippedOrderItems.keySet();
    for (String orderId : orders) {

        // we'll only use this list to figure out which ones to send
        List<GenericValue> billItems = shippedOrderItems.get(orderId);

        // a new list to be used to pass to the create invoice service
        List<GenericValue> toBillItems = new LinkedList<GenericValue>();

        // map of available quantities so we only have to calc once
        Map<String, BigDecimal> itemQtyAvail = new HashMap<String, BigDecimal>();

        // now we will check each issuance and make sure it hasn't already been billed
        for (GenericValue issue : billItems) {
            BigDecimal issueQty = ZERO;

            if (issue.getEntityName().equals("ShipmentReceipt")) {
                issueQty = issue.getBigDecimal("quantityAccepted");
            } else {
                issueQty = issue.getBigDecimal("quantity");
            }

            BigDecimal billAvail = itemQtyAvail.get(issue.getString("orderItemSeqId"));
            if (billAvail == null) {
                List<EntityCondition> lookup = new LinkedList<EntityCondition>();
                lookup.add(EntityCondition.makeCondition("orderId", orderId));
                lookup.add(EntityCondition.makeCondition("orderItemSeqId", issue.get("orderItemSeqId")));
                lookup.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL,
                        "INVOICE_CANCELLED"));
                GenericValue orderItem = null;
                List<GenericValue> billed = null;
                BigDecimal orderedQty = null;
                try {
                    orderItem = issue.getEntityName().equals("OrderItem") ? issue
                            : issue.getRelatedOne("OrderItem", false);

                    // total ordered
                    orderedQty = orderItem.getBigDecimal("quantity");

                    if (dropShipmentFound && createSalesInvoicesForDropShipments.booleanValue()) {

                        // Override the issueQty with the quantity from the purchase order item
                        GenericValue orderItemAssoc = EntityUtil.getFirst(EntityUtil.filterByAnd(
                                orderItemAssocs, UtilMisc.toMap("orderId", issue.getString("orderId"),
                                        "orderItemSeqId", issue.getString("orderItemSeqId"))));
                        GenericValue purchaseOrderItem = orderItemAssoc.getRelatedOne("ToOrderItem", false);
                        orderItem.set("quantity", purchaseOrderItem.getBigDecimal("quantity"));
                        issueQty = purchaseOrderItem.getBigDecimal("quantity");
                    }
                    billed = EntityQuery.use(delegator).from("OrderItemBillingAndInvoiceAndItem").where(lookup)
                            .queryList();
                } catch (GenericEntityException e) {
                    Debug.logError(e, "Problem getting OrderItem/OrderItemBilling records " + lookup, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                            "AccountingProblemGettingOrderItemOrderItemBilling",
                            UtilMisc.toMap("lookup", lookup), locale));
                }

                // add up the already billed total
                if (billed.size() > 0) {
                    BigDecimal billedQuantity = ZERO;
                    for (GenericValue oib : billed) {
                        BigDecimal qty = oib.getBigDecimal("quantity");
                        if (qty != null) {
                            billedQuantity = billedQuantity.add(qty).setScale(DECIMALS, ROUNDING);
                        }
                    }
                    BigDecimal leftToBill = orderedQty.subtract(billedQuantity).setScale(DECIMALS, ROUNDING);
                    billAvail = leftToBill;
                } else {
                    billAvail = orderedQty;
                }
            }

            // no available means we cannot bill anymore
            if (billAvail != null && billAvail.signum() == 1) { // this checks if billAvail is a positive non-zero number
                if (issueQty != null && issueQty.compareTo(billAvail) > 0) {
                    // can only bill some of the issuance; others have been billed already
                    if ("ShipmentReceipt".equals(issue.getEntityName())) {
                        issue.set("quantityAccepted", billAvail);
                    } else {
                        issue.set("quantity", billAvail);
                    }
                    billAvail = ZERO;
                } else {
                    // now have been billed
                    billAvail = billAvail.subtract(issueQty).setScale(DECIMALS, ROUNDING);
                }

                // okay to bill these items; but none else
                toBillItems.add(issue);
            }

            // update the available to bill quantity for the next pass
            itemQtyAvail.put(issue.getString("orderItemSeqId"), billAvail);
        }

        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);

        GenericValue productStore = orh.getProductStore();
        String prorateShipping = productStore != null ? productStore.getString("prorateShipping") : "N";

        // If shipping charges are not prorated, the shipments need to be examined for additional shipping charges
        if ("N".equalsIgnoreCase(prorateShipping)) {

            // Get the set of filtered shipments
            List<GenericValue> invoiceableShipments = null;
            try {
                if (dropShipmentFound) {

                    List<String> invoiceablePrimaryOrderIds = null;
                    if (createSalesInvoicesForDropShipments) {

                        // If a sales invoice is being created for the drop shipment, we need to reference back to the original purchase order IDs

                        // Get the IDs for orders which have billable items
                        List<String> invoiceableLinkedOrderIds = EntityUtil
                                .getFieldListFromEntityList(toBillItems, "orderId", true);

                        // Get back the IDs of the purchase orders - this will be a list of the purchase order items which are billable by virtue of not having been
                        //  invoiced in a previous sales invoice
                        List<GenericValue> reverseOrderItemAssocs = EntityUtil
                                .filterByCondition(orderItemAssocs, EntityCondition.makeCondition("orderId",
                                        EntityOperator.IN, invoiceableLinkedOrderIds));
                        invoiceablePrimaryOrderIds = EntityUtil
                                .getFieldListFromEntityList(reverseOrderItemAssocs, "toOrderId", true);

                    } else {

                        // If a purchase order is being created for a drop shipment, the purchase order IDs can be used directly
                        invoiceablePrimaryOrderIds = EntityUtil.getFieldListFromEntityList(toBillItems,
                                "orderId", true);

                    }

                    // Get the list of shipments which are associated with the filtered purchase orders
                    if (!UtilValidate.isEmpty(invoiceablePrimaryOrderIds)) {
                        invoiceableShipments = EntityQuery.use(delegator).from("Shipment")
                                .where(UtilMisc.toList(
                                        EntityCondition.makeCondition("primaryOrderId", EntityOperator.IN,
                                                invoiceablePrimaryOrderIds),
                                        EntityCondition.makeCondition("shipmentId", EntityOperator.IN,
                                                shipmentIds)))
                                .queryList();
                    }
                } else {
                    List<String> invoiceableShipmentIds = EntityUtil.getFieldListFromEntityList(toBillItems,
                            "shipmentId", true);
                    if (UtilValidate.isNotEmpty(invoiceableShipmentIds)) {
                        invoiceableShipments = EntityQuery
                                .use(delegator).from("Shipment").where(EntityCondition
                                        .makeCondition("shipmentId", EntityOperator.IN, invoiceableShipmentIds))
                                .queryList();
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, "Trouble calling createInvoicesFromShipments service", module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                        "AccountingTroubleCallingCreateInvoicesFromShipmentsService", locale));
            }

            // Total the additional shipping charges for the shipments
            Map<GenericValue, BigDecimal> additionalShippingCharges = new HashMap<GenericValue, BigDecimal>();
            BigDecimal totalAdditionalShippingCharges = ZERO;
            if (UtilValidate.isNotEmpty(invoiceableShipments)) {
                for (GenericValue shipment : invoiceableShipments) {
                    if (shipment.get("additionalShippingCharge") == null)
                        continue;
                    BigDecimal shipmentAdditionalShippingCharges = shipment
                            .getBigDecimal("additionalShippingCharge").setScale(DECIMALS, ROUNDING);
                    additionalShippingCharges.put(shipment, shipmentAdditionalShippingCharges);
                    totalAdditionalShippingCharges = totalAdditionalShippingCharges
                            .add(shipmentAdditionalShippingCharges);
                }
            }

            // If the additional shipping charges are greater than zero, process them
            if (totalAdditionalShippingCharges.signum() == 1) {

                // Add an OrderAdjustment to the order for each additional shipping charge
                for (Map.Entry<GenericValue, BigDecimal> entry : additionalShippingCharges.entrySet()) {
                    GenericValue shipment = entry.getKey();
                    BigDecimal additionalShippingCharge = entry.getValue();
                    String shipmentId = shipment.getString("shipmentId");
                    Map<String, Object> createOrderAdjustmentContext = new HashMap<String, Object>();
                    createOrderAdjustmentContext.put("orderId", orderId);
                    createOrderAdjustmentContext.put("orderAdjustmentTypeId", "SHIPPING_CHARGES");
                    String addtlChargeDescription = shipment.getString("addtlShippingChargeDesc");
                    if (UtilValidate.isEmpty(addtlChargeDescription)) {
                        addtlChargeDescription = UtilProperties.getMessage(resource,
                                "AccountingAdditionalShippingChargeForShipment",
                                UtilMisc.toMap("shipmentId", shipmentId), locale);
                    }
                    createOrderAdjustmentContext.put("description", addtlChargeDescription);
                    createOrderAdjustmentContext.put("sourceReferenceId", shipmentId);
                    createOrderAdjustmentContext.put("amount", additionalShippingCharge);
                    createOrderAdjustmentContext.put("userLogin", context.get("userLogin"));
                    String shippingOrderAdjustmentId = null;
                    try {
                        Map<String, Object> createOrderAdjustmentResult = dispatcher
                                .runSync("createOrderAdjustment", createOrderAdjustmentContext);
                        shippingOrderAdjustmentId = (String) createOrderAdjustmentResult
                                .get("orderAdjustmentId");
                    } catch (GenericServiceException e) {
                        Debug.logError(e, "Trouble calling createOrderAdjustment service", module);
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                "AccountingTroubleCallingCreateOrderAdjustmentService", locale));
                    }

                    // Obtain a list of OrderAdjustments due to tax on the shipping charges, if any
                    GenericValue billToParty = orh.getBillToParty();
                    GenericValue payToParty = orh.getBillFromParty();
                    GenericValue destinationContactMech = null;
                    try {
                        destinationContactMech = shipment.getRelatedOne("DestinationPostalAddress", false);
                    } catch (GenericEntityException e) {
                        Debug.logError(e,
                                "Trouble calling createInvoicesFromShipment service; invoice not created for shipment "
                                        + shipmentId,
                                module);
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                "AccountingTroubleCallingCreateInvoicesFromShipmentService", locale));
                    }

                    List<Object> emptyList = new LinkedList<Object>();
                    Map<String, Object> calcTaxContext = new HashMap<String, Object>();
                    calcTaxContext.put("productStoreId", orh.getProductStoreId());
                    calcTaxContext.put("payToPartyId", payToParty.getString("partyId"));
                    calcTaxContext.put("billToPartyId", billToParty.getString("partyId"));
                    calcTaxContext.put("orderShippingAmount", totalAdditionalShippingCharges);
                    calcTaxContext.put("shippingAddress", destinationContactMech);

                    // These parameters don't matter if we're only worried about adjustments on the shipping charges
                    calcTaxContext.put("itemProductList", emptyList);
                    calcTaxContext.put("itemAmountList", emptyList);
                    calcTaxContext.put("itemPriceList", emptyList);
                    calcTaxContext.put("itemQuantityList", emptyList);
                    calcTaxContext.put("itemShippingList", emptyList);

                    Map<String, Object> calcTaxResult = null;
                    try {
                        calcTaxResult = dispatcher.runSync("calcTax", calcTaxContext);
                    } catch (GenericServiceException e) {
                        Debug.logError(e, "Trouble calling calcTaxService", module);
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                "AccountingTroubleCallingCalcTaxService", locale));
                    }
                    List<GenericValue> orderAdjustments = UtilGenerics
                            .checkList(calcTaxResult.get("orderAdjustments"));

                    // If we have any OrderAdjustments due to tax on shipping, store them and add them to the total
                    if (orderAdjustments != null) {
                        for (GenericValue orderAdjustment : orderAdjustments) {
                            totalAdditionalShippingCharges = totalAdditionalShippingCharges
                                    .add(orderAdjustment.getBigDecimal("amount").setScale(DECIMALS, ROUNDING));
                            orderAdjustment.set("orderAdjustmentId", delegator.getNextSeqId("OrderAdjustment"));
                            orderAdjustment.set("orderId", orderId);
                            orderAdjustment.set("orderItemSeqId", "_NA_");
                            orderAdjustment.set("shipGroupSeqId", shipment.getString("primaryShipGroupSeqId"));
                            orderAdjustment.set("originalAdjustmentId", shippingOrderAdjustmentId);
                        }
                        try {
                            delegator.storeAll(orderAdjustments);
                        } catch (GenericEntityException e) {
                            Debug.logError(e, "Problem storing OrderAdjustments: " + orderAdjustments, module);
                            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                    "AccountingProblemStoringOrderAdjustments",
                                    UtilMisc.toMap("orderAdjustments", orderAdjustments), locale));
                        }
                    }

                    // If part of the order was paid via credit card, try to charge it for the additional shipping
                    List<GenericValue> orderPaymentPreferences = null;
                    try {
                        orderPaymentPreferences = EntityQuery.use(delegator).from("OrderPaymentPreference")
                                .where("orderId", orderId, "paymentMethodTypeId", "CREDIT_CARD").queryList();
                    } catch (GenericEntityException e) {
                        Debug.logError(e, "Problem getting OrderPaymentPreference records", module);
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                "AccountingProblemGettingOrderPaymentPreferences", locale));
                    }

                    //  Use the first credit card we find, for the sake of simplicity
                    String paymentMethodId = null;
                    GenericValue cardOrderPaymentPref = EntityUtil.getFirst(orderPaymentPreferences);
                    if (cardOrderPaymentPref != null) {
                        paymentMethodId = cardOrderPaymentPref.getString("paymentMethodId");
                    }

                    if (paymentMethodId != null) {

                        // Release all outstanding (not settled or cancelled) authorizations, while keeping a running
                        //  total of their amounts so that the total plus the additional shipping charges can be authorized again
                        //  all at once.
                        BigDecimal totalNewAuthAmount = totalAdditionalShippingCharges.setScale(DECIMALS,
                                ROUNDING);
                        for (GenericValue orderPaymentPreference : orderPaymentPreferences) {
                            if (!(orderPaymentPreference.getString("statusId").equals("PAYMENT_SETTLED")
                                    || orderPaymentPreference.getString("statusId")
                                            .equals("PAYMENT_CANCELLED"))) {
                                GenericValue authTransaction = PaymentGatewayServices
                                        .getAuthTransaction(orderPaymentPreference);
                                if (authTransaction != null && authTransaction.get("amount") != null) {

                                    // Update the total authorized amount
                                    totalNewAuthAmount = totalNewAuthAmount.add(authTransaction
                                            .getBigDecimal("amount").setScale(DECIMALS, ROUNDING));

                                    // Release the authorization for the OrderPaymentPreference
                                    Map<String, Object> prefReleaseResult = null;
                                    try {
                                        prefReleaseResult = dispatcher.runSync("releaseOrderPaymentPreference",
                                                UtilMisc.toMap("orderPaymentPreferenceId",
                                                        orderPaymentPreference
                                                                .getString("orderPaymentPreferenceId"),
                                                        "userLogin", context.get("userLogin")));
                                    } catch (GenericServiceException e) {
                                        Debug.logError(e,
                                                "Trouble calling releaseOrderPaymentPreference service",
                                                module);
                                        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                                "AccountingTroubleCallingReleaseOrderPaymentPreferenceService",
                                                locale));
                                    }
                                    if (ServiceUtil.isError(prefReleaseResult)
                                            || ServiceUtil.isFailure(prefReleaseResult)) {
                                        String errMsg = ServiceUtil.getErrorMessage(prefReleaseResult);
                                        Debug.logError(errMsg, module);
                                        return ServiceUtil.returnError(errMsg);
                                    }
                                }
                            }
                        }

                        // Create a new OrderPaymentPreference for the order to handle the new (totalled) charge. Don't
                        //  set the maxAmount so that it doesn't interfere with other authorizations
                        Map<String, Object> serviceContext = UtilMisc.toMap("orderId", orderId,
                                "paymentMethodId", paymentMethodId, "paymentMethodTypeId", "CREDIT_CARD",
                                "userLogin", context.get("userLogin"));
                        String orderPaymentPreferenceId = null;
                        try {
                            Map<String, Object> result = dispatcher.runSync("createOrderPaymentPreference",
                                    serviceContext);
                            orderPaymentPreferenceId = (String) result.get("orderPaymentPreferenceId");
                        } catch (GenericServiceException e) {
                            Debug.logError(e, "Trouble calling createOrderPaymentPreference service", module);
                            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                    "AccountingTroubleCallingCreateOrderPaymentPreferenceService", locale));
                        }

                        // Attempt to authorize the new orderPaymentPreference
                        Map<String, Object> authResult = null;
                        try {
                            // Use an overrideAmount because the maxAmount wasn't set on the OrderPaymentPreference
                            authResult = dispatcher.runSync("authOrderPaymentPreference",
                                    UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId,
                                            "overrideAmount", totalNewAuthAmount, "userLogin",
                                            context.get("userLogin")));
                        } catch (GenericServiceException e) {
                            Debug.logError(e, "Trouble calling authOrderPaymentPreference service", module);
                            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                                    "AccountingTroubleCallingAuthOrderPaymentPreferenceService", locale));
                        }

                        // If the authorization fails, create the invoice anyway, but make a note of it
                        boolean authFinished = ((Boolean) authResult.get("finished")).booleanValue();
                        boolean authErrors = ((Boolean) authResult.get("errors")).booleanValue();
                        if (authErrors || !authFinished) {
                            String errMsg = UtilProperties.getMessage(resource,
                                    "AccountingUnableToAuthAdditionalShipCharges",
                                    UtilMisc.toMap("shipmentId", shipmentId, "paymentMethodId", paymentMethodId,
                                            "orderPaymentPreferenceId", orderPaymentPreferenceId),
                                    locale);
                            Debug.logError(errMsg, module);
                        }

                    }
                }
            }
        } else {
            Debug.logInfo(UtilProperties.getMessage(resource, "AccountingIgnoringAdditionalShipCharges",
                    UtilMisc.toMap("productStoreId", orh.getProductStoreId()), locale), module);
        }

        String invoiceId = null;
        GenericValue shipmentItemBilling = null;
        String shipmentId = shipmentIds.get(0);
        try {
            shipmentItemBilling = EntityQuery.use(delegator).from("ShipmentItemBilling")
                    .where("shipmentId", shipmentId).queryFirst();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(
                    UtilProperties.getMessage(resource, "AccountingProblemGettingShipmentItemBilling", locale));
        }
        if (shipmentItemBilling != null) {
            invoiceId = shipmentItemBilling.getString("invoiceId");
        }

        // call the createInvoiceForOrder service for each order
        Map<String, Object> serviceContext = UtilMisc.toMap("orderId", orderId, "billItems", toBillItems,
                "invoiceId", invoiceId, "eventDate", context.get("eventDate"), "userLogin",
                context.get("userLogin"));
        try {
            Map<String, Object> result = dispatcher.runSync("createInvoiceForOrder", serviceContext);
            invoicesCreated.add((String) result.get("invoiceId"));
        } catch (GenericServiceException e) {
            Debug.logError(e, "Trouble calling createInvoiceForOrder service; invoice not created for shipment",
                    module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                    "AccountingTroubleCallingCreateInvoiceForOrderService", locale));
        }
    }

    Map<String, Object> response = ServiceUtil.returnSuccess();
    response.put("invoicesCreated", invoicesCreated);
    return response;
}

From source file:com.gst.portfolio.loanaccount.domain.Loan.java

public Money adjustDisburseAmount(final JsonCommand command, final LocalDate actualDisbursementDate) {
    Money disburseAmount = this.loanRepaymentScheduleDetail.getPrincipal().zero();
    BigDecimal principalDisbursed = command
            .bigDecimalValueOfParameterNamed(LoanApiConstants.principalDisbursedParameterName);
    if (this.actualDisbursementDate == null) {
        this.actualDisbursementDate = actualDisbursementDate.toDate();
    }//from   w w  w . j a  v  a 2s.c  o  m
    BigDecimal diff = BigDecimal.ZERO;
    Collection<LoanDisbursementDetails> details = fetchUndisbursedDetail();
    if (principalDisbursed == null) {
        disburseAmount = this.loanRepaymentScheduleDetail.getPrincipal();
        if (!details.isEmpty()) {
            disburseAmount = disburseAmount.zero();
            for (LoanDisbursementDetails disbursementDetails : details) {
                disbursementDetails.updateActualDisbursementDate(actualDisbursementDate.toDate());
                disburseAmount = disburseAmount.plus(disbursementDetails.principal());
            }
        }
    } else {
        if (this.loanProduct.isMultiDisburseLoan()) {
            disburseAmount = Money.of(getCurrency(), principalDisbursed);
        } else {
            disburseAmount = disburseAmount.plus(principalDisbursed);
        }

        if (details.isEmpty()) {
            diff = this.loanRepaymentScheduleDetail.getPrincipal().minus(principalDisbursed).getAmount();
        } else {
            for (LoanDisbursementDetails disbursementDetails : details) {
                disbursementDetails.updateActualDisbursementDate(actualDisbursementDate.toDate());
                disbursementDetails.updatePrincipal(principalDisbursed);
            }
        }
        if (this.loanProduct().isMultiDisburseLoan()) {
            Collection<LoanDisbursementDetails> loanDisburseDetails = this.getDisbursementDetails();
            BigDecimal setPrincipalAmount = BigDecimal.ZERO;
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (LoanDisbursementDetails disbursementDetails : loanDisburseDetails) {
                if (disbursementDetails.actualDisbursementDate() != null) {
                    setPrincipalAmount = setPrincipalAmount.add(disbursementDetails.principal());
                }
                totalAmount = totalAmount.add(disbursementDetails.principal());
            }
            this.loanRepaymentScheduleDetail.setPrincipal(setPrincipalAmount);
            if (totalAmount.compareTo(this.approvedPrincipal) == 1) {
                final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved principal ";
                throw new LoanDisbursalException(errorMsg,
                        "disburse.amount.must.be.less.than.approved.principal", principalDisbursed,
                        this.approvedPrincipal);
            }
        } else {
            this.loanRepaymentScheduleDetail
                    .setPrincipal(this.loanRepaymentScheduleDetail.getPrincipal().minus(diff).getAmount());
        }
        if (!(this.loanProduct().isMultiDisburseLoan()) && diff.compareTo(BigDecimal.ZERO) == -1) {
            final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved amount ";
            throw new LoanDisbursalException(errorMsg, "disburse.amount.must.be.less.than.approved.amount",
                    principalDisbursed, this.loanRepaymentScheduleDetail.getPrincipal().getAmount());
        }
    }
    return disburseAmount;
}

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  .  j  ava 2  s .c om*/

    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:com.lp.server.fertigung.ejbfac.FertigungFacBean.java

private void createReservierung(ArtikelDto artikelDto, Integer iBelegartpositionid, BigDecimal bdMenge,
        Timestamp tLiefertermin) throws EJBExceptionLP {
    try {/*from   www.j a va2  s  . c om*/
        // nur wenn die Menge > 0 ist
        if (bdMenge.compareTo(new BigDecimal(0)) != 0) {
            ArtikelreservierungDto resDto = new ArtikelreservierungDto();
            resDto.setArtikelIId(artikelDto.getIId());
            resDto.setCBelegartnr(LocaleFac.BELEGART_LOS);
            resDto.setIBelegartpositionid(iBelegartpositionid);
            resDto.setNMenge(bdMenge);
            resDto.setTLiefertermin(tLiefertermin);
            getReservierungFac().createArtikelreservierung(resDto);
        }
    } catch (RemoteException ex) {
        throwEJBExceptionLPRespectOld(ex);
    }
}

From source file:com.lp.server.fertigung.ejbfac.FertigungFacBean.java

public void pruefePositionenMitSollsatzgroesseUnterschreitung(Integer losIId, BigDecimal bdZuErledigendeMenge,
        TheClientDto theClientDto) throws EJBExceptionLP {

    // Basis fuer die Sollsatzgroesse sind die bisher erledigte Menge und
    // die zu erledigende
    BigDecimal bdKuenftigErledigt = getErledigteMenge(losIId, theClientDto).add(bdZuErledigendeMenge);
    LosDto losDto = losFindByPrimaryKey(losIId);
    // es sollte von jeder Position ein prozentueller Anteil ausgegeben sein
    // der prozentsatz wird durch die kuenftig erl. Menge im Verhaeltnis zur
    // Losgroesse bestimmt
    BigDecimal bdFaktor = bdKuenftigErledigt.divide(losDto.getNLosgroesse(), 10, BigDecimal.ROUND_HALF_EVEN);
    // alle Positionen holen
    LossollmaterialDto[] sollmat = lossollmaterialFindByLosIId(losIId);
    LinkedList<LossollmaterialDto> listUnterschritten = new LinkedList<LossollmaterialDto>();
    // fuer jede einzelne soll- und istmenge vergleichen
    for (int i = 0; i < sollmat.length; i++) {
        // bisher ausgegebene Menge
        BigDecimal bdAusgegeben = getAusgegebeneMenge(sollmat[i].getIId(), null, theClientDto);
        // Die soll-ausgabe menge berechnen
        BigDecimal bdSollAusgabeMenge = Helper.rundeKaufmaennisch(sollmat[i].getNMenge().multiply(bdFaktor), 3);
        if (bdSollAusgabeMenge.compareTo(bdAusgegeben) > 0) {
            // Wenn die soll-ausgabe-menge noch nicht erreicht ist, dann zur
            // Liste hinzufuegen
            listUnterschritten.add(sollmat[i]);
        }//from  ww w. j a v a 2 s  .  com
    }
    // und jetzt noch ein Array aus der Liste bauen
    LossollmaterialDto[] sollmatUnterschritten = new LossollmaterialDto[listUnterschritten.size()];
    int i = 0;
    for (Iterator<?> iter = listUnterschritten.iterator(); iter.hasNext(); i++) {
        sollmatUnterschritten[i] = (LossollmaterialDto) iter.next();
    }

    if (sollmatUnterschritten.length > 0) {

        StringBuffer sText = new StringBuffer(getTextRespectUISpr("fert.sollsatzgroesseunterschritten",
                theClientDto.getMandant(), theClientDto.getLocUi()));

        String stkl = getTextRespectUISpr("lp.stueckliste", theClientDto.getMandant(), theClientDto.getLocUi());

        for (int j = 0; j < sollmatUnterschritten.length; j++) {
            sText.append("\n");

            if (losDto.getStuecklisteIId() != null) {
                sText.append(stkl);
                StuecklisteDto stklDto = getStuecklisteFac()
                        .stuecklisteFindByPrimaryKey(losDto.getStuecklisteIId(), theClientDto);
                sText.append(" " + stklDto.getArtikelDto().getCNr() + ": ");
            }

            ArtikelDto artikelDto = getArtikelFac()
                    .artikelFindByPrimaryKey(sollmatUnterschritten[j].getArtikelIId(), theClientDto);
            sText.append(artikelDto.formatArtikelbezeichnung());

        }
        ArrayList ai = new ArrayList();
        ai.add(sText);
        throw new EJBExceptionLP(EJBExceptionLP.FEHLER_FERTIGUNG_SOLLSATZGROESSE_UNTERSCHRITTEN, ai,
                new Exception("losIId == null"));

    }
}

From source file:com.lp.server.fertigung.ejbfac.FertigungFacBean.java

private void updateReservierung(ArtikelDto artikelDto, Integer iBelegartpositionid, BigDecimal bdMenge,
        Timestamp tLiefertermin) throws EJBExceptionLP {
    try {//from w w  w .  ja  v  a  2s .co  m
        if (Helper.short2boolean(artikelDto.getBLagerbewirtschaftet())) {
            if (bdMenge.compareTo(new BigDecimal(0)) != 0) {
                ArtikelreservierungDto resDto = getReservierungFac()
                        .artikelreservierungFindByBelegartCNrBelegartPositionIIdOhneExc(LocaleFac.BELEGART_LOS,
                                iBelegartpositionid);
                if (resDto != null) {
                    // falls der artikel geaendert wurde
                    resDto.setArtikelIId(artikelDto.getIId());
                    resDto.setNMenge(bdMenge);
                    resDto.setTLiefertermin(tLiefertermin);
                    getReservierungFac().updateArtikelreservierung(resDto);
                } else {
                    // ansonsten neu anlegen
                    resDto = new ArtikelreservierungDto();
                    resDto.setCBelegartnr(LocaleFac.BELEGART_LOS);
                    resDto.setIBelegartpositionid(iBelegartpositionid);
                    resDto.setArtikelIId(artikelDto.getIId());
                    resDto.setNMenge(bdMenge);
                    resDto.setTLiefertermin(tLiefertermin);
                    getReservierungFac().createArtikelreservierung(resDto);
                }

            } else {
                // wenn menge = 0 dann loeschen
                getReservierungFac().removeArtikelreservierung(LocaleFac.BELEGART_LOS, iBelegartpositionid);
            }
        }
    } catch (RemoteException ex) {
        throwEJBExceptionLPRespectOld(ex);
    }
}

From source file:com.lp.server.fertigung.ejbfac.FertigungFacBean.java

private BigDecimal getErledigterMaterialwertEinerSollpositionNEU(BigDecimal bdLosgroesse,
        BigDecimal bdErledigteMenge, TheClientDto theClientDto, LosDto losDto, BigDecimal bdAusgegeben,
        BigDecimal gesamtpreis, BigDecimal sollmenge) {

    // wenn volle menge erledigt oder sogar mehr oder Los=erledigt
    if (bdLosgroesse.compareTo(bdErledigteMenge) <= 0
            || losDto.getStatusCNr().equals(FertigungFac.STATUS_ERLEDIGT)) {
        // dann alles
        return gesamtpreis;
    } else {//from  www .  j ava2  s. c  o m
        // Sollsatzgroesse berechnen
        BigDecimal bdSollsatzgroesse = sollmenge.multiply(bdErledigteMenge).divide(bdLosgroesse, 6,
                BigDecimal.ROUND_HALF_EVEN);
        // weniger oder gleich wie sollmenge ausgegeben
        if (bdAusgegeben.compareTo(bdSollsatzgroesse) <= 0) {
            // dann alles
            return gesamtpreis;
        }
        // wenn mehr ausgegeben
        else {

            BigDecimal bdEinzelpreis = new BigDecimal(0);

            if (bdAusgegeben.doubleValue() > 0) {
                bdEinzelpreis = gesamtpreis.divide(bdAusgegeben, 4, BigDecimal.ROUND_HALF_EVEN);
            }

            // dann mit sollsatzgroesse
            return bdSollsatzgroesse.multiply(bdEinzelpreis);
        }
    }
}

From source file:com.lp.server.fertigung.ejbfac.FertigungFacBean.java

public void bucheFehlmengenNach(LosDto losDto, LossollmaterialDto[] sollmat, TheClientDto theClientDto) {
    try {//w  w  w.j  a  va2 s  .c om

        // Laeger des Loses
        LoslagerentnahmeDto[] laeger = loslagerentnahmeFindByLosIId(losDto.getIId());
        // nun vom lager abbuchen
        for (int i = 0; i < sollmat.length; i++) {
            ArtikelDto artikelDto = getArtikelFac().artikelFindByPrimaryKey(sollmat[i].getArtikelIId(),
                    theClientDto);
            // seriennummerntragende werden jetzt gar nicht gebucht

            ArtikelfehlmengeDto artikelfehlemngeDto = getFehlmengeFac()
                    .artikelfehlmengeFindByBelegartCNrBelegartPositionIIdOhneExc(LocaleFac.BELEGART_LOS,
                            sollmat[i].getIId());

            if (artikelfehlemngeDto != null) {

                BigDecimal bdAbzubuchendeMenge = artikelfehlemngeDto.getNMenge();
                if (!Helper.short2boolean(artikelDto.getBSeriennrtragend())) {
                    if (!Helper.short2boolean(artikelDto.getBChargennrtragend())) {
                        for (int j = 0; j < laeger.length; j++) {
                            // wenn noch was abzubuchen ist (Menge > 0)
                            if (bdAbzubuchendeMenge.compareTo(new BigDecimal(0)) == 1) {
                                BigDecimal bdLagerstand = null;
                                if (Helper.short2boolean(artikelDto.getBLagerbewirtschaftet())) {
                                    bdLagerstand = getLagerFac().getLagerstand(artikelDto.getIId(),
                                            laeger[j].getLagerIId(), theClientDto);

                                } else {
                                    bdLagerstand = new BigDecimal(999999999);
                                }
                                // wenn ein lagerstand da ist
                                if (bdLagerstand.compareTo(new BigDecimal(0)) == 1) {
                                    BigDecimal bdMengeVonLager;
                                    if (bdLagerstand.compareTo(bdAbzubuchendeMenge) == 1) {
                                        // wenn mehr als ausreichend auf
                                        // lager
                                        bdMengeVonLager = bdAbzubuchendeMenge;
                                    } else {
                                        // dann nur den lagerstand entnehmen
                                        bdMengeVonLager = bdLagerstand;
                                    }
                                    LosistmaterialDto istmat = new LosistmaterialDto();
                                    istmat.setLagerIId(laeger[j].getLagerIId());
                                    istmat.setLossollmaterialIId(sollmat[i].getIId());
                                    istmat.setNMenge(bdMengeVonLager);
                                    istmat.setBAbgang(Helper.boolean2Short(true));
                                    // ist-wert anlegen und lagerbuchung
                                    // durchfuehren
                                    createLosistmaterial(istmat, null, theClientDto);
                                    // menge reduzieren
                                    bdAbzubuchendeMenge = bdAbzubuchendeMenge.subtract(bdMengeVonLager);
                                }
                            }
                        }
                    }
                } else {
                    /**
                     * @todo falls nur eine charge auf lager ist -> trotzdem
                     *       buchen PJ 4220
                     */
                }

            }

        }

    } catch (RemoteException ex) {
        throwEJBExceptionLPRespectOld(ex);
    }

}