Example usage for java.math BigDecimal multiply

List of usage examples for java.math BigDecimal multiply

Introduction

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

Prototype

public BigDecimal multiply(BigDecimal multiplicand) 

Source Link

Document

Returns a BigDecimal whose value is (this × multiplicand), and whose scale is (this.scale() + multiplicand.scale()) .

Usage

From source file:org.ofbiz.order.order.OrderServices.java

/**
 * Determines the total amount invoiced for a given order item over all invoices by totalling the item subtotal (via OrderItemBilling),
 *  any adjustments for that item (via OrderAdjustmentBilling), and the item's share of any order-level adjustments (that calculated
 *  by applying the percentage of the items total that the item represents to the order-level adjustments total (also via
 *  OrderAdjustmentBilling). Also returns the quantity invoiced for the item over all invoices, to aid in prorating.
 * @param dctx DispatchContext//w w  w .j  av a  2s  .  co  m
 * @param context Map
 * @return Map
 */
public static Map<String, Object> getOrderItemInvoicedAmountAndQuantity(DispatchContext dctx,
        Map<String, ? extends Object> context) {
    Delegator delegator = dctx.getDelegator();
    Locale locale = (Locale) context.get("locale");

    String orderId = (String) context.get("orderId");
    String orderItemSeqId = (String) context.get("orderItemSeqId");

    GenericValue orderHeader = null;
    GenericValue orderItemToCheck = null;
    BigDecimal orderItemTotalValue = ZERO;
    BigDecimal invoicedQuantity = ZERO; // Quantity invoiced for the target order item
    try {

        orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
        if (UtilValidate.isEmpty(orderHeader)) {
            String errorMessage = UtilProperties.getMessage(resource_error, "OrderErrorOrderIdNotFound",
                    context, locale);
            Debug.logError(errorMessage, module);
            return ServiceUtil.returnError(errorMessage);
        }
        orderItemToCheck = delegator.findByPrimaryKey("OrderItem",
                UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItemSeqId));
        if (UtilValidate.isEmpty(orderItemToCheck)) {
            String errorMessage = UtilProperties.getMessage(resource_error, "OrderErrorOrderItemNotFound",
                    context, locale);
            Debug.logError(errorMessage, module);
            return ServiceUtil.returnError(errorMessage);
        }

        BigDecimal orderItemsSubtotal = ZERO; // Aggregated value of order items, non-tax and non-shipping item-level adjustments
        BigDecimal invoicedTotal = ZERO; // Amount invoiced for the target order item
        BigDecimal itemAdjustments = ZERO; // Item-level tax- and shipping-adjustments

        // Aggregate the order items subtotal
        List<GenericValue> orderItems = orderHeader.getRelated("OrderItem", UtilMisc.toList("orderItemSeqId"));
        Iterator<GenericValue> oit = orderItems.iterator();
        while (oit.hasNext()) {
            GenericValue orderItem = oit.next();

            // Look at the orderItemBillings to discover the amount and quantity ever invoiced for this order item
            List<GenericValue> orderItemBillings = delegator.findByAnd("OrderItemBilling",
                    UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId")));
            Iterator<GenericValue> oibit = orderItemBillings.iterator();
            while (oibit.hasNext()) {
                GenericValue orderItemBilling = oibit.next();
                BigDecimal quantity = orderItemBilling.getBigDecimal("quantity");
                BigDecimal amount = orderItemBilling.getBigDecimal("amount").setScale(orderDecimals,
                        orderRounding);
                if (UtilValidate.isEmpty(invoicedQuantity) || UtilValidate.isEmpty(amount))
                    continue;

                // Add the item base amount to the subtotal
                orderItemsSubtotal = orderItemsSubtotal.add(quantity.multiply(amount));

                // If the item is the target order item, add the invoiced quantity and amount to their respective totals
                if (orderItemSeqId.equals(orderItem.get("orderItemSeqId"))) {
                    invoicedQuantity = invoicedQuantity.add(quantity);
                    invoicedTotal = invoicedTotal.add(quantity.multiply(amount));
                }
            }

            // Retrieve the adjustments for this item
            List<GenericValue> orderAdjustments = delegator.findByAnd("OrderAdjustment",
                    UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId")));
            Iterator<GenericValue> oait = orderAdjustments.iterator();
            while (oait.hasNext()) {
                GenericValue orderAdjustment = oait.next();
                String orderAdjustmentTypeId = orderAdjustment.getString("orderAdjustmentTypeId");
                boolean includeInTax = orderAdjustment.getBoolean("includeInTax").booleanValue();
                // Look at the orderAdjustmentBillings to discove the amount ever invoiced for this order adjustment
                List<GenericValue> orderAdjustmentBillings = delegator.findByAnd("OrderAdjustmentBilling",
                        UtilMisc.toMap("orderAdjustmentId", orderAdjustment.get("orderAdjustmentId")));
                Iterator<GenericValue> oabit = orderAdjustmentBillings.iterator();
                while (oabit.hasNext()) {
                    GenericValue orderAjustmentBilling = oabit.next();
                    BigDecimal amount = orderAjustmentBilling.getBigDecimal("amount").setScale(orderDecimals,
                            orderRounding);
                    if (UtilValidate.isEmpty(amount))
                        continue;

                    if (includeInTax || "SALES_TAX".equals(orderAdjustmentTypeId)
                            || "SHIPPING_CHARGES".equals(orderAdjustmentTypeId)) {
                        if (orderItemSeqId.equals(orderItem.get("orderItemSeqId"))) {

                            // Add tax- and shipping-adjustment amounts to the total adjustments for the target order item
                            itemAdjustments = itemAdjustments.add(amount);
                        }
                    } else {

                        // Add non-tax and non-shipping adjustment amounts to the order items subtotal
                        orderItemsSubtotal = orderItemsSubtotal.add(amount);
                        if (orderItemSeqId.equals(orderItem.get("orderItemSeqId"))) {

                            // If the item is the target order item, add non-tax and non-shipping adjustment amounts to the invoiced total
                            invoicedTotal = invoicedTotal.add(amount);
                        }
                    }
                }
            }
        }

        // Total the order-header-level adjustments for the order
        BigDecimal orderHeaderAdjustmentsTotalValue = ZERO;
        List<GenericValue> orderHeaderAdjustments = delegator.findByAnd("OrderAdjustment",
                UtilMisc.toMap("orderId", orderId, "orderItemSeqId", "_NA_"));
        Iterator<GenericValue> ohait = orderHeaderAdjustments.iterator();
        while (ohait.hasNext()) {
            GenericValue orderHeaderAdjustment = ohait.next();
            List<GenericValue> orderHeaderAdjustmentBillings = delegator.findByAnd("OrderAdjustmentBilling",
                    UtilMisc.toMap("orderAdjustmentId", orderHeaderAdjustment.get("orderAdjustmentId")));
            Iterator<GenericValue> ohabit = orderHeaderAdjustmentBillings.iterator();
            while (ohabit.hasNext()) {
                GenericValue orderHeaderAdjustmentBilling = ohabit.next();
                BigDecimal amount = orderHeaderAdjustmentBilling.getBigDecimal("amount").setScale(orderDecimals,
                        orderRounding);
                if (UtilValidate.isEmpty(amount))
                    continue;
                orderHeaderAdjustmentsTotalValue = orderHeaderAdjustmentsTotalValue.add(amount);
            }
        }

        // How much of the order-level adjustments total does the target order item represent? The assumption is: the same
        //  proportion of the adjustments as of the invoiced total for the item to the invoiced total for all items. These
        //  figures don't take tax- and shipping- adjustments into account, so as to be in accordance with the code in InvoiceServices
        BigDecimal invoicedAmountProportion = ZERO;
        if (orderItemsSubtotal.signum() != 0) {
            invoicedAmountProportion = invoicedTotal.divide(orderItemsSubtotal, 5, orderRounding);
        }
        BigDecimal orderItemHeaderAjustmentAmount = orderHeaderAdjustmentsTotalValue
                .multiply(invoicedAmountProportion);
        orderItemTotalValue = invoicedTotal.add(orderItemHeaderAjustmentAmount);

        // Add back the tax- and shipping- item-level adjustments for the order item
        orderItemTotalValue = orderItemTotalValue.add(itemAdjustments);

    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }

    Map<String, Object> result = ServiceUtil.returnSuccess();
    result.put("invoicedAmount", orderItemTotalValue.setScale(orderDecimals, orderRounding));
    result.put("invoicedQuantity", invoicedQuantity.setScale(orderDecimals, orderRounding));
    return result;
}

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

public static Map<String, Object> createInvoiceFromReturn(DispatchContext dctx, Map<String, Object> context) {
    Delegator delegator = dctx.getDelegator();
    LocalDispatcher dispatcher = dctx.getDispatcher();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    Locale locale = (Locale) context.get("locale");

    String returnId = (String) context.get("returnId");
    List<GenericValue> billItems = UtilGenerics.checkList(context.get("billItems"));
    String errorMsg = UtilProperties.getMessage(resource, "AccountingErrorCreatingInvoiceForReturn",
            UtilMisc.toMap("returnId", returnId), locale);
    // List invoicesCreated = new ArrayList();
    try {// w w w .j  av a2s.  c  o  m
        String invoiceTypeId;
        String description;
        // get the return header
        GenericValue returnHeader = EntityQuery.use(delegator).from("ReturnHeader").where("returnId", returnId)
                .queryOne();
        if (returnHeader == null || returnHeader.get("returnHeaderTypeId") == null) {
            return ServiceUtil.returnError(
                    UtilProperties.getMessage(resource, "AccountingReturnTypeCannotBeNull", locale));
        }

        if (returnHeader.getString("returnHeaderTypeId").startsWith("CUSTOMER_")) {
            invoiceTypeId = "CUST_RTN_INVOICE";
            description = "Return Invoice for Customer Return #" + returnId;
        } else {
            invoiceTypeId = "PURC_RTN_INVOICE";
            description = "Return Invoice for Vendor Return #" + returnId;
        }

        List<GenericValue> returnItems = returnHeader.getRelated("ReturnItem", null, null, false);
        if (!returnItems.isEmpty()) {
            for (GenericValue returnItem : returnItems) {
                if ("RETURN_COMPLETED".equals(returnItem.getString("statusId"))) {
                    GenericValue product = returnItem.getRelatedOne("Product", false);
                    if (!ProductWorker.isPhysical(product)) {
                        boolean isNonPhysicalItemToReturn = false;
                        List<GenericValue> returnItemBillings = returnItem.getRelated("ReturnItemBilling", null,
                                null, false);

                        if (!returnItemBillings.isEmpty()) {
                            GenericValue invoice = EntityUtil.getFirst(returnItemBillings)
                                    .getRelatedOne("Invoice", false);
                            if ("INVOICE_CANCELLED".equals(invoice.getString("statusId"))) {
                                isNonPhysicalItemToReturn = true;
                            }
                        } else {
                            isNonPhysicalItemToReturn = true;
                        }

                        if (isNonPhysicalItemToReturn) {
                            if (UtilValidate.isEmpty(billItems)) {
                                billItems = new ArrayList<GenericValue>();
                            }

                            billItems.add(returnItem);
                        }
                    }
                }
            }
        }

        Map<String, Object> results = ServiceUtil.returnSuccess();
        if (UtilValidate.isNotEmpty(billItems)) {
            // set the invoice data
            Map<String, Object> input = UtilMisc.<String, Object>toMap("invoiceTypeId", invoiceTypeId,
                    "statusId", "INVOICE_IN_PROCESS");
            input.put("partyId", returnHeader.get("toPartyId"));
            input.put("partyIdFrom", returnHeader.get("fromPartyId"));
            input.put("currencyUomId", returnHeader.get("currencyUomId"));
            input.put("invoiceDate", UtilDateTime.nowTimestamp());
            input.put("description", description);
            input.put("billingAccountId", returnHeader.get("billingAccountId"));
            input.put("userLogin", userLogin);

            // call the service to create the invoice
            Map<String, Object> serviceResults = dispatcher.runSync("createInvoice", input);
            if (ServiceUtil.isError(serviceResults)) {
                return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
            }
            String invoiceId = (String) serviceResults.get("invoiceId");

            // keep track of the invoice total vs the promised return total (how much the customer promised to return)
            BigDecimal invoiceTotal = ZERO;
            BigDecimal promisedTotal = ZERO;

            // loop through shipment receipts to create invoice items and return item billings for each item and adjustment
            int invoiceItemSeqNum = 1;
            String invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                    INVOICE_ITEM_SEQUENCE_ID_DIGITS);

            for (GenericValue item : billItems) {
                boolean shipmentReceiptFound = false;
                boolean itemIssuanceFound = false;
                GenericValue returnItem = null;
                BigDecimal quantity = BigDecimal.ZERO;

                if ("ShipmentReceipt".equals(item.getEntityName())) {
                    shipmentReceiptFound = true;
                } else if ("ItemIssuance".equals(item.getEntityName())) {
                    itemIssuanceFound = true;
                } else if ("ReturnItem".equals(item.getEntityName())) {
                    quantity = item.getBigDecimal("returnQuantity");
                    returnItem = item;
                } else {
                    Debug.logError("Unexpected entity " + item + " of type " + item.getEntityName(), module);
                }
                // we need the related return item and product
                if (shipmentReceiptFound) {
                    returnItem = item.getRelatedOne("ReturnItem", true);
                } else if (itemIssuanceFound) {
                    GenericValue shipmentItem = item.getRelatedOne("ShipmentItem", true);
                    GenericValue returnItemShipment = EntityUtil
                            .getFirst(shipmentItem.getRelated("ReturnItemShipment", null, null, false));
                    returnItem = returnItemShipment.getRelatedOne("ReturnItem", true);
                }
                if (returnItem == null)
                    continue; // Just to prevent NPE
                GenericValue product = returnItem.getRelatedOne("Product", true);

                // extract the return price as a big decimal for convenience
                BigDecimal returnPrice = returnItem.getBigDecimal("returnPrice");

                // determine invoice item type from the return item type
                String invoiceItemTypeId = getInvoiceItemType(delegator,
                        returnItem.getString("returnItemTypeId"), null, invoiceTypeId, null);
                if (invoiceItemTypeId == null) {
                    return ServiceUtil.returnError(errorMsg + UtilProperties.getMessage(resource,
                            "AccountingNoKnownInvoiceItemTypeReturnItemType",
                            UtilMisc.toMap("returnItemTypeId", returnItem.getString("returnItemTypeId")),
                            locale));
                }
                if (shipmentReceiptFound) {
                    quantity = item.getBigDecimal("quantityAccepted");
                } else if (itemIssuanceFound) {
                    quantity = item.getBigDecimal("quantity");
                }

                // create the invoice item for this shipment receipt
                input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId,
                        "quantity", quantity);
                input.put("invoiceItemSeqId", "" + invoiceItemSeqId); // turn the int into a string with ("" + int) hack
                input.put("amount", returnItem.get("returnPrice"));
                input.put("productId", returnItem.get("productId"));
                input.put("taxableFlag", product.get("taxable"));
                input.put("description", returnItem.get("description"));
                // TODO: what about the productFeatureId?
                input.put("userLogin", userLogin);
                serviceResults = dispatcher.runSync("createInvoiceItem", input);
                if (ServiceUtil.isError(serviceResults)) {
                    return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
                }

                // copy the return item information into ReturnItemBilling
                input = UtilMisc.toMap("returnId", returnId, "returnItemSeqId",
                        returnItem.get("returnItemSeqId"), "invoiceId", invoiceId);
                input.put("invoiceItemSeqId", "" + invoiceItemSeqId); // turn the int into a string with ("" + int) hack
                input.put("quantity", quantity);
                input.put("amount", returnItem.get("returnPrice"));
                input.put("userLogin", userLogin);
                if (shipmentReceiptFound) {
                    input.put("shipmentReceiptId", item.get("receiptId"));
                }
                serviceResults = dispatcher.runSync("createReturnItemBilling", input);
                if (ServiceUtil.isError(serviceResults)) {
                    return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
                }
                if (Debug.verboseOn()) {
                    Debug.logVerbose("Creating Invoice Item with amount " + returnPrice + " and quantity "
                            + quantity + " for shipment [" + item.getString("shipmentId") + ":"
                            + item.getString("shipmentItemSeqId") + "]", module);
                }

                String parentInvoiceItemSeqId = invoiceItemSeqId;
                // increment the seqId counter after creating the invoice item and return item billing
                invoiceItemSeqNum += 1;
                invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                        INVOICE_ITEM_SEQUENCE_ID_DIGITS);

                // keep a running total (note: a returnItem may have many receipts. hence, the promised total quantity is the receipt quantityAccepted + quantityRejected)
                BigDecimal cancelQuantity = ZERO;
                if (shipmentReceiptFound) {
                    cancelQuantity = item.getBigDecimal("quantityRejected");
                } else if (itemIssuanceFound) {
                    cancelQuantity = item.getBigDecimal("cancelQuantity");
                }
                if (cancelQuantity == null)
                    cancelQuantity = ZERO;
                BigDecimal actualAmount = returnPrice.multiply(quantity).setScale(DECIMALS, ROUNDING);
                BigDecimal promisedAmount = returnPrice.multiply(quantity.add(cancelQuantity))
                        .setScale(DECIMALS, ROUNDING);
                invoiceTotal = invoiceTotal.add(actualAmount).setScale(DECIMALS, ROUNDING);
                promisedTotal = promisedTotal.add(promisedAmount).setScale(DECIMALS, ROUNDING);

                // for each adjustment related to this ReturnItem, create a separate invoice item
                List<GenericValue> adjustments = returnItem.getRelated("ReturnAdjustment", null, null, true);
                for (GenericValue adjustment : adjustments) {

                    if (adjustment.get("amount") == null) {
                        Debug.logWarning("Return adjustment [" + adjustment.get("returnAdjustmentId")
                                + "] has null amount and will be skipped", module);
                        continue;
                    }

                    // determine invoice item type from the return item type
                    invoiceItemTypeId = getInvoiceItemType(delegator,
                            adjustment.getString("returnAdjustmentTypeId"), null, invoiceTypeId, null);
                    if (invoiceItemTypeId == null) {
                        return ServiceUtil
                                .returnError(
                                        errorMsg + UtilProperties.getMessage(resource,
                                                "AccountingNoKnownInvoiceItemTypeReturnAdjustmentType",
                                                UtilMisc.toMap("returnAdjustmentTypeId",
                                                        adjustment.getString("returnAdjustmentTypeId")),
                                                locale));
                    }

                    // prorate the adjustment amount by the returned amount; do not round ratio
                    BigDecimal ratio = quantity.divide(returnItem.getBigDecimal("returnQuantity"), 100,
                            ROUNDING);
                    BigDecimal amount = adjustment.getBigDecimal("amount");
                    amount = amount.multiply(ratio).setScale(DECIMALS, ROUNDING);
                    if (Debug.verboseOn()) {
                        Debug.logVerbose("Creating Invoice Item with amount "
                                + adjustment.getBigDecimal("amount") + " prorated to " + amount
                                + " for return adjustment [" + adjustment.getString("returnAdjustmentId") + "]",
                                module);
                    }

                    // prepare invoice item data for this adjustment
                    input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId,
                            "quantity", BigDecimal.ONE);
                    input.put("amount", amount);
                    input.put("invoiceItemSeqId", "" + invoiceItemSeqId); // turn the int into a string with ("" + int) hack
                    input.put("productId", returnItem.get("productId"));
                    input.put("description", adjustment.get("description"));
                    input.put("overrideGlAccountId", adjustment.get("overrideGlAccountId"));
                    input.put("parentInvoiceId", invoiceId);
                    input.put("parentInvoiceItemSeqId", parentInvoiceItemSeqId);
                    input.put("taxAuthPartyId", adjustment.get("taxAuthPartyId"));
                    input.put("taxAuthGeoId", adjustment.get("taxAuthGeoId"));
                    input.put("userLogin", userLogin);

                    // only set taxable flag when the adjustment is not a tax
                    // TODO: Note that we use the value of Product.taxable here. This is not an ideal solution. Instead, use returnAdjustment.includeInTax
                    if (adjustment.get("returnAdjustmentTypeId").equals("RET_SALES_TAX_ADJ")) {
                        input.put("taxableFlag", "N");
                    }

                    // create the invoice item
                    serviceResults = dispatcher.runSync("createInvoiceItem", input);
                    if (ServiceUtil.isError(serviceResults)) {
                        return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
                    }

                    // increment the seqId counter
                    invoiceItemSeqNum += 1;
                    invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                            INVOICE_ITEM_SEQUENCE_ID_DIGITS);

                    // keep a running total (promised adjustment in this case is the same as the invoice adjustment)
                    invoiceTotal = invoiceTotal.add(amount).setScale(DECIMALS, ROUNDING);
                    promisedTotal = promisedTotal.add(amount).setScale(DECIMALS, ROUNDING);
                }
            }

            // ratio of the invoice total to the promised total so far or zero if the amounts were zero
            BigDecimal actualToPromisedRatio = ZERO;
            if (invoiceTotal.signum() != 0) {
                actualToPromisedRatio = invoiceTotal.divide(promisedTotal, 100, ROUNDING); // do not round ratio
            }

            // loop through return-wide adjustments and create invoice items for each
            List<GenericValue> adjustments = returnHeader.getRelated("ReturnAdjustment",
                    UtilMisc.toMap("returnItemSeqId", "_NA_"), null, true);
            for (GenericValue adjustment : adjustments) {

                // determine invoice item type from the return item type
                String invoiceItemTypeId = getInvoiceItemType(delegator,
                        adjustment.getString("returnAdjustmentTypeId"), null, invoiceTypeId, null);
                if (invoiceItemTypeId == null) {
                    return ServiceUtil
                            .returnError(
                                    errorMsg + UtilProperties
                                            .getMessage(resource,
                                                    "AccountingNoKnownInvoiceItemTypeReturnAdjustmentType",
                                                    UtilMisc.toMap("returnAdjustmentTypeId",
                                                            adjustment.getString("returnAdjustmentTypeId")),
                                                    locale));
                }

                // prorate the adjustment amount by the actual to promised ratio
                BigDecimal amount = adjustment.getBigDecimal("amount").multiply(actualToPromisedRatio)
                        .setScale(DECIMALS, ROUNDING);
                if (Debug.verboseOn()) {
                    Debug.logVerbose("Creating Invoice Item with amount " + adjustment.getBigDecimal("amount")
                            + " prorated to " + amount + " for return adjustment ["
                            + adjustment.getString("returnAdjustmentId") + "]", module);
                }

                // prepare the invoice item for the return-wide adjustment
                input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId,
                        "quantity", BigDecimal.ONE);
                input.put("amount", amount);
                input.put("invoiceItemSeqId", "" + invoiceItemSeqId); // turn the int into a string with ("" + int) hack
                input.put("description", adjustment.get("description"));
                input.put("overrideGlAccountId", adjustment.get("overrideGlAccountId"));
                input.put("taxAuthPartyId", adjustment.get("taxAuthPartyId"));
                input.put("taxAuthGeoId", adjustment.get("taxAuthGeoId"));
                input.put("userLogin", userLogin);

                // XXX TODO Note: we need to implement ReturnAdjustment.includeInTax for this to work properly
                input.put("taxableFlag", adjustment.get("includeInTax"));

                // create the invoice item
                serviceResults = dispatcher.runSync("createInvoiceItem", input);
                if (ServiceUtil.isError(serviceResults)) {
                    return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
                }

                // increment the seqId counter
                invoiceItemSeqNum += 1;
                invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                        INVOICE_ITEM_SEQUENCE_ID_DIGITS);
            }

            // Set the invoice to READY
            serviceResults = dispatcher.runSync("setInvoiceStatus", UtilMisc.<String, Object>toMap("invoiceId",
                    invoiceId, "statusId", "INVOICE_READY", "userLogin", userLogin));
            if (ServiceUtil.isError(serviceResults)) {
                return ServiceUtil.returnError(errorMsg, null, null, serviceResults);
            }

            // return the invoiceId
            results.put("invoiceId", invoiceId);
        }
        return results;
    } catch (GenericServiceException e) {
        Debug.logError(e, errorMsg + e.getMessage(), module);
        return ServiceUtil.returnError(errorMsg + e.getMessage());
    } catch (GenericEntityException e) {
        Debug.logError(e, errorMsg + e.getMessage(), module);
        return ServiceUtil.returnError(errorMsg + e.getMessage());
    }
}

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

public static Map<String, Object> createInvoiceForOrder(DispatchContext dctx, Map<String, Object> context) {
    Delegator delegator = dctx.getDelegator();
    LocalDispatcher dispatcher = dctx.getDispatcher();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    Locale locale = (Locale) context.get("locale");

    if (DECIMALS == -1 || ROUNDING == -1) {
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingAritmeticPropertiesNotConfigured", locale));
    }//from w  ww. j  av a2  s . c  o m

    String orderId = (String) context.get("orderId");
    List<GenericValue> billItems = UtilGenerics.checkList(context.get("billItems"));
    String invoiceId = (String) context.get("invoiceId");

    if (UtilValidate.isEmpty(billItems)) {
        Debug.logVerbose("No order items to invoice; not creating invoice; returning success", module);
        return ServiceUtil
                .returnSuccess(UtilProperties.getMessage(resource, "AccountingNoOrderItemsToInvoice", locale));
    }

    try {
        GenericValue orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId)
                .queryOne();
        if (orderHeader == null) {
            return ServiceUtil
                    .returnError(UtilProperties.getMessage(resource, "AccountingNoOrderHeader", locale));
        }

        // figure out the invoice type
        String invoiceType = null;

        String orderType = orderHeader.getString("orderTypeId");
        if (orderType.equals("SALES_ORDER")) {
            invoiceType = "SALES_INVOICE";
        } else if (orderType.equals("PURCHASE_ORDER")) {
            invoiceType = "PURCHASE_INVOICE";
        }

        // Set the precision depending on the type of invoice
        int invoiceTypeDecimals = UtilNumber.getBigDecimalScale("invoice." + invoiceType + ".decimals");
        if (invoiceTypeDecimals == -1)
            invoiceTypeDecimals = DECIMALS;

        // Make an order read helper from the order
        OrderReadHelper orh = new OrderReadHelper(orderHeader);

        // get the product store
        GenericValue productStore = orh.getProductStore();

        // get the shipping adjustment mode (Y = Pro-Rate; N = First-Invoice)
        String prorateShipping = productStore != null ? productStore.getString("prorateShipping") : "Y";
        if (prorateShipping == null) {
            prorateShipping = "Y";
        }

        // get the billing parties
        String billToCustomerPartyId = orh.getBillToParty().getString("partyId");
        String billFromVendorPartyId = orh.getBillFromParty().getString("partyId");

        // get some price totals
        BigDecimal shippableAmount = orh.getShippableTotal(null);
        BigDecimal shippableQuantity = orh.getShippableQuantity(null);
        BigDecimal orderSubTotal = orh.getOrderItemsSubTotal();
        BigDecimal orderQuantity = orh.getTotalOrderItemsQuantity();

        // these variables are for pro-rating order amounts across invoices, so they should not be rounded off for maximum accuracy
        BigDecimal invoiceShipProRateAmount = ZERO;
        BigDecimal invoiceShippableQuantity = ZERO;
        BigDecimal invoiceSubTotal = ZERO;
        BigDecimal invoiceQuantity = ZERO;

        GenericValue billingAccount = orderHeader.getRelatedOne("BillingAccount", false);
        String billingAccountId = billingAccount != null ? billingAccount.getString("billingAccountId") : null;

        Timestamp invoiceDate = (Timestamp) context.get("eventDate");
        if (UtilValidate.isEmpty(invoiceDate)) {
            // TODO: ideally this should be the same time as when a shipment is sent and be passed in as a parameter
            invoiceDate = UtilDateTime.nowTimestamp();
        }
        // TODO: perhaps consider billing account net days term as well?
        Long orderTermNetDays = orh.getOrderTermNetDays();
        Timestamp dueDate = null;
        if (orderTermNetDays != null) {
            dueDate = UtilDateTime.getDayEnd(invoiceDate, orderTermNetDays);
        }

        // create the invoice record
        if (UtilValidate.isEmpty(invoiceId)) {
            Map<String, Object> createInvoiceContext = new HashMap<String, Object>();
            createInvoiceContext.put("partyId", billToCustomerPartyId);
            createInvoiceContext.put("partyIdFrom", billFromVendorPartyId);
            createInvoiceContext.put("billingAccountId", billingAccountId);
            createInvoiceContext.put("invoiceDate", invoiceDate);
            createInvoiceContext.put("dueDate", dueDate);
            createInvoiceContext.put("invoiceTypeId", invoiceType);
            // start with INVOICE_IN_PROCESS, in the INVOICE_READY we can't change the invoice (or shouldn't be able to...)
            createInvoiceContext.put("statusId", "INVOICE_IN_PROCESS");
            createInvoiceContext.put("currencyUomId", orderHeader.getString("currencyUom"));
            createInvoiceContext.put("userLogin", userLogin);

            // store the invoice first
            Map<String, Object> createInvoiceResult = dispatcher.runSync("createInvoice", createInvoiceContext);
            if (ServiceUtil.isError(createInvoiceResult)) {
                return ServiceUtil.returnError(
                        UtilProperties.getMessage(resource, "AccountingErrorCreatingInvoiceFromOrder", locale),
                        null, null, createInvoiceResult);
            }

            // call service, not direct entity op: delegator.create(invoice);
            invoiceId = (String) createInvoiceResult.get("invoiceId");
        }

        // order roles to invoice roles
        List<GenericValue> orderRoles = orderHeader.getRelated("OrderRole", null, null, false);
        Map<String, Object> createInvoiceRoleContext = new HashMap<String, Object>();
        createInvoiceRoleContext.put("invoiceId", invoiceId);
        createInvoiceRoleContext.put("userLogin", userLogin);
        for (GenericValue orderRole : orderRoles) {
            createInvoiceRoleContext.put("partyId", orderRole.getString("partyId"));
            createInvoiceRoleContext.put("roleTypeId", orderRole.getString("roleTypeId"));
            Map<String, Object> createInvoiceRoleResult = dispatcher.runSync("createInvoiceRole",
                    createInvoiceRoleContext);
            if (ServiceUtil.isError(createInvoiceRoleResult)) {
                return ServiceUtil.returnError(
                        UtilProperties.getMessage(resource, "AccountingErrorCreatingInvoiceFromOrder", locale),
                        null, null, createInvoiceRoleResult);
            }
        }

        // order terms to invoice terms.
        // TODO: it might be nice to filter OrderTerms to only copy over financial terms.
        List<GenericValue> orderTerms = orh.getOrderTerms();
        createInvoiceTerms(delegator, dispatcher, invoiceId, orderTerms, userLogin, locale);

        // billing accounts
        // List billingAccountTerms = null;
        // for billing accounts we will use related information
        if (billingAccount != null) {
            /*
             * jacopoc: billing account terms were already copied as order terms
             *          when the order was created.
            // get the billing account terms
            billingAccountTerms = billingAccount.getRelated("BillingAccountTerm", null, null, false);
                    
            // set the invoice terms as defined for the billing account
            createInvoiceTerms(delegator, dispatcher, invoiceId, billingAccountTerms, userLogin, locale);
            */
            // set the invoice bill_to_customer from the billing account
            List<GenericValue> billToRoles = billingAccount.getRelated("BillingAccountRole",
                    UtilMisc.toMap("roleTypeId", "BILL_TO_CUSTOMER"), null, false);
            for (GenericValue billToRole : billToRoles) {
                if (!(billToRole.getString("partyId").equals(billToCustomerPartyId))) {
                    createInvoiceRoleContext = UtilMisc.toMap("invoiceId", invoiceId, "partyId",
                            billToRole.get("partyId"), "roleTypeId", "BILL_TO_CUSTOMER", "userLogin",
                            userLogin);
                    Map<String, Object> createInvoiceRoleResult = dispatcher.runSync("createInvoiceRole",
                            createInvoiceRoleContext);
                    if (ServiceUtil.isError(createInvoiceRoleResult)) {
                        return ServiceUtil.returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingInvoiceRoleFromOrder", locale),
                                null, null, createInvoiceRoleResult);
                    }
                }
            }

            // set the bill-to contact mech as the contact mech of the billing account
            if (UtilValidate.isNotEmpty(billingAccount.getString("contactMechId"))) {
                Map<String, Object> createBillToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId,
                        "contactMechId", billingAccount.getString("contactMechId"), "contactMechPurposeTypeId",
                        "BILLING_LOCATION", "userLogin", userLogin);
                Map<String, Object> createBillToContactMechResult = dispatcher
                        .runSync("createInvoiceContactMech", createBillToContactMechContext);
                if (ServiceUtil.isError(createBillToContactMechResult)) {
                    return ServiceUtil.returnError(
                            UtilProperties.getMessage(resource,
                                    "AccountingErrorCreatingInvoiceContactMechFromOrder", locale),
                            null, null, createBillToContactMechResult);
                }
            }
        } else {
            List<GenericValue> billingLocations = orh.getBillingLocations();
            if (UtilValidate.isNotEmpty(billingLocations)) {
                for (GenericValue ocm : billingLocations) {
                    Map<String, Object> createBillToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId,
                            "contactMechId", ocm.getString("contactMechId"), "contactMechPurposeTypeId",
                            "BILLING_LOCATION", "userLogin", userLogin);
                    Map<String, Object> createBillToContactMechResult = dispatcher
                            .runSync("createInvoiceContactMech", createBillToContactMechContext);
                    if (ServiceUtil.isError(createBillToContactMechResult)) {
                        return ServiceUtil.returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingInvoiceContactMechFromOrder", locale),
                                null, null, createBillToContactMechResult);
                    }
                }
            } else {
                Debug.logWarning("No billing locations found for order [" + orderId
                        + "] and none were created for Invoice [" + invoiceId + "]", module);
            }
        }

        // get a list of the payment method types
        //DEJ20050705 doesn't appear to be used: List paymentPreferences = orderHeader.getRelated("OrderPaymentPreference", null, null, false);

        // create the bill-from (or pay-to) contact mech as the primary PAYMENT_LOCATION of the party from the store
        GenericValue payToAddress = null;
        if (invoiceType.equals("PURCHASE_INVOICE")) {
            // for purchase orders, the pay to address is the BILLING_LOCATION of the vendor
            GenericValue billFromVendor = orh.getPartyFromRole("BILL_FROM_VENDOR");
            if (billFromVendor != null) {
                List<GenericValue> billingContactMechs = billFromVendor.getRelatedOne("Party", false)
                        .getRelated("PartyContactMechPurpose",
                                UtilMisc.toMap("contactMechPurposeTypeId", "BILLING_LOCATION"), null, false);
                if (UtilValidate.isNotEmpty(billingContactMechs)) {
                    payToAddress = EntityUtil.getFirst(billingContactMechs);
                }
            }
        } else {
            // for sales orders, it is the payment address on file for the store
            payToAddress = PaymentWorker.getPaymentAddress(delegator, productStore.getString("payToPartyId"));
        }
        if (payToAddress != null) {
            Map<String, Object> createPayToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId,
                    "contactMechId", payToAddress.getString("contactMechId"), "contactMechPurposeTypeId",
                    "PAYMENT_LOCATION", "userLogin", userLogin);
            Map<String, Object> createPayToContactMechResult = dispatcher.runSync("createInvoiceContactMech",
                    createPayToContactMechContext);
            if (ServiceUtil.isError(createPayToContactMechResult)) {
                return ServiceUtil.returnError(
                        UtilProperties.getMessage(resource,
                                "AccountingErrorCreatingInvoiceContactMechFromOrder", locale),
                        null, null, createPayToContactMechResult);
            }
        }

        // sequence for items - all OrderItems or InventoryReservations + all Adjustments
        int invoiceItemSeqNum = 1;
        String invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                INVOICE_ITEM_SEQUENCE_ID_DIGITS);

        // create the item records
        for (GenericValue currentValue : billItems) {
            GenericValue itemIssuance = null;
            GenericValue orderItem = null;
            GenericValue shipmentReceipt = null;
            if ("ItemIssuance".equals(currentValue.getEntityName())) {
                itemIssuance = currentValue;
            } else if ("OrderItem".equals(currentValue.getEntityName())) {
                orderItem = currentValue;
            } else if ("ShipmentReceipt".equals(currentValue.getEntityName())) {
                shipmentReceipt = currentValue;
            } else {
                Debug.logError("Unexpected entity " + currentValue + " of type " + currentValue.getEntityName(),
                        module);
            }

            if (orderItem == null && itemIssuance != null) {
                orderItem = itemIssuance.getRelatedOne("OrderItem", false);
            } else if ((orderItem == null) && (shipmentReceipt != null)) {
                orderItem = shipmentReceipt.getRelatedOne("OrderItem", false);
            } else if ((orderItem == null) && (itemIssuance == null) && (shipmentReceipt == null)) {
                Debug.logError(
                        "Cannot create invoice when orderItem, itemIssuance, and shipmentReceipt are all null",
                        module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                        "AccountingIllegalValuesPassedToCreateInvoiceService", locale));
            }
            GenericValue product = null;
            if (orderItem.get("productId") != null) {
                product = orderItem.getRelatedOne("Product", false);
            }

            // get some quantities
            BigDecimal billingQuantity = null;
            if (itemIssuance != null) {
                billingQuantity = itemIssuance.getBigDecimal("quantity");
                BigDecimal cancelQty = itemIssuance.getBigDecimal("cancelQuantity");
                if (cancelQty == null) {
                    cancelQty = ZERO;
                }
                billingQuantity = billingQuantity.subtract(cancelQty).setScale(DECIMALS, ROUNDING);
            } else if (shipmentReceipt != null) {
                billingQuantity = shipmentReceipt.getBigDecimal("quantityAccepted");
            } else {
                BigDecimal orderedQuantity = OrderReadHelper.getOrderItemQuantity(orderItem);
                BigDecimal invoicedQuantity = OrderReadHelper.getOrderItemInvoicedQuantity(orderItem);
                billingQuantity = orderedQuantity.subtract(invoicedQuantity);
                if (billingQuantity.compareTo(ZERO) < 0) {
                    billingQuantity = ZERO;
                }
            }
            if (billingQuantity == null)
                billingQuantity = ZERO;

            // check if shipping applies to this item.  Shipping is calculated for sales invoices, not purchase invoices.
            boolean shippingApplies = false;
            if ((product != null) && (ProductWorker.shippingApplies(product))
                    && (invoiceType.equals("SALES_INVOICE"))) {
                shippingApplies = true;
            }

            BigDecimal billingAmount = BigDecimal.ZERO;
            GenericValue OrderAdjustment = EntityUtil.getFirst(orderItem.getRelated("OrderAdjustment",
                    UtilMisc.toMap("orderAdjustmentTypeId", "VAT_TAX"), null, false));
            /* Apply formula to get actual product price to set amount in invoice item
            Formula is: productPrice = (productPriceWithTax.multiply(100)) / (orderAdj sourcePercentage + 100))
            product price = (43*100) / (20+100) = 35.83 (Here product price is 43 with VAT)
             */
            if (UtilValidate.isNotEmpty(OrderAdjustment)
                    && (OrderAdjustment.getBigDecimal("amount").signum() == 0)
                    && UtilValidate.isNotEmpty(OrderAdjustment.getBigDecimal("amountAlreadyIncluded"))
                    && OrderAdjustment.getBigDecimal("amountAlreadyIncluded").signum() != 0) {
                BigDecimal sourcePercentageTotal = OrderAdjustment.getBigDecimal("sourcePercentage")
                        .add(new BigDecimal(100));
                billingAmount = orderItem.getBigDecimal("unitPrice")
                        .divide(sourcePercentageTotal, 100, ROUNDING).multiply(new BigDecimal(100))
                        .setScale(invoiceTypeDecimals, ROUNDING);
            } else {
                billingAmount = orderItem.getBigDecimal("unitPrice").setScale(invoiceTypeDecimals, ROUNDING);
            }

            Map<String, Object> createInvoiceItemContext = new HashMap<String, Object>();
            createInvoiceItemContext.put("invoiceId", invoiceId);
            createInvoiceItemContext.put("invoiceItemSeqId", invoiceItemSeqId);
            createInvoiceItemContext.put("invoiceItemTypeId",
                    getInvoiceItemType(delegator, (orderItem.getString("orderItemTypeId")),
                            (product == null ? null : product.getString("productTypeId")), invoiceType,
                            "INV_FPROD_ITEM"));
            createInvoiceItemContext.put("description", orderItem.get("itemDescription"));
            createInvoiceItemContext.put("quantity", billingQuantity);
            createInvoiceItemContext.put("amount", billingAmount);
            createInvoiceItemContext.put("productId", orderItem.get("productId"));
            createInvoiceItemContext.put("productFeatureId", orderItem.get("productFeatureId"));
            createInvoiceItemContext.put("overrideGlAccountId", orderItem.get("overrideGlAccountId"));
            createInvoiceItemContext.put("userLogin", userLogin);

            String itemIssuanceId = null;
            if (itemIssuance != null && itemIssuance.get("inventoryItemId") != null) {
                itemIssuanceId = itemIssuance.getString("itemIssuanceId");
                createInvoiceItemContext.put("inventoryItemId", itemIssuance.get("inventoryItemId"));
            }
            // similarly, tax only for purchase invoices
            if ((product != null) && (invoiceType.equals("SALES_INVOICE"))) {
                createInvoiceItemContext.put("taxableFlag", product.get("taxable"));
            }

            Map<String, Object> createInvoiceItemResult = dispatcher.runSync("createInvoiceItem",
                    createInvoiceItemContext);
            if (ServiceUtil.isError(createInvoiceItemResult)) {
                return ServiceUtil
                        .returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingInvoiceItemFromOrder", locale),
                                null, null, createInvoiceItemResult);
            }

            // this item total
            BigDecimal thisAmount = billingAmount.multiply(billingQuantity).setScale(invoiceTypeDecimals,
                    ROUNDING);

            // add to the ship amount only if it applies to this item
            if (shippingApplies) {
                invoiceShipProRateAmount = invoiceShipProRateAmount.add(thisAmount)
                        .setScale(invoiceTypeDecimals, ROUNDING);
                invoiceShippableQuantity = invoiceQuantity.add(billingQuantity).setScale(invoiceTypeDecimals,
                        ROUNDING);
            }

            // increment the invoice subtotal
            invoiceSubTotal = invoiceSubTotal.add(thisAmount).setScale(100, ROUNDING);

            // increment the invoice quantity
            invoiceQuantity = invoiceQuantity.add(billingQuantity).setScale(invoiceTypeDecimals, ROUNDING);

            // create the OrderItemBilling record
            Map<String, Object> createOrderItemBillingContext = new HashMap<String, Object>();
            createOrderItemBillingContext.put("invoiceId", invoiceId);
            createOrderItemBillingContext.put("invoiceItemSeqId", invoiceItemSeqId);
            createOrderItemBillingContext.put("orderId", orderItem.get("orderId"));
            createOrderItemBillingContext.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
            createOrderItemBillingContext.put("itemIssuanceId", itemIssuanceId);
            createOrderItemBillingContext.put("quantity", billingQuantity);
            createOrderItemBillingContext.put("amount", billingAmount);
            createOrderItemBillingContext.put("userLogin", userLogin);
            if ((shipmentReceipt != null) && (shipmentReceipt.getString("receiptId") != null)) {
                createOrderItemBillingContext.put("shipmentReceiptId", shipmentReceipt.getString("receiptId"));
            }

            Map<String, Object> createOrderItemBillingResult = dispatcher.runSync("createOrderItemBilling",
                    createOrderItemBillingContext);
            if (ServiceUtil.isError(createOrderItemBillingResult)) {
                return ServiceUtil
                        .returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingOrderItemBillingFromOrder", locale),
                                null, null, createOrderItemBillingResult);
            }

            if ("ItemIssuance".equals(currentValue.getEntityName())) {
                /* Find ShipmentItemBilling based on shipmentId, shipmentItemSeqId, invoiceId, invoiceItemSeqId as
                   because if any order item has multiple quantity and reserved by multiple inventories then there will be multiple invoice items.
                   In that case ShipmentItemBilling was creating only for one invoice item. Fixed under OFBIZ-6806.
                */
                List<GenericValue> shipmentItemBillings = EntityQuery.use(delegator).from("ShipmentItemBilling")
                        .where("shipmentId", currentValue.get("shipmentId"), "shipmentItemSeqId",
                                currentValue.get("shipmentItemSeqId"), "invoiceId", invoiceId,
                                "invoiceItemSeqId", invoiceItemSeqId)
                        .queryList();
                if (UtilValidate.isEmpty(shipmentItemBillings)) {

                    // create the ShipmentItemBilling record
                    GenericValue shipmentItemBilling = delegator.makeValue("ShipmentItemBilling",
                            UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId));
                    shipmentItemBilling.put("shipmentId", currentValue.get("shipmentId"));
                    shipmentItemBilling.put("shipmentItemSeqId", currentValue.get("shipmentItemSeqId"));
                    shipmentItemBilling.create();
                }
            }

            String parentInvoiceItemSeqId = invoiceItemSeqId;
            // increment the counter
            invoiceItemSeqNum++;
            invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                    INVOICE_ITEM_SEQUENCE_ID_DIGITS);

            // Get the original order item from the DB, in case the quantity has been overridden
            GenericValue originalOrderItem = EntityQuery.use(delegator).from("OrderItem")
                    .where("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId")).queryOne();

            // create the item adjustment as line items
            List<GenericValue> itemAdjustments = OrderReadHelper.getOrderItemAdjustmentList(orderItem,
                    orh.getAdjustments());
            for (GenericValue adj : itemAdjustments) {

                // Check against OrderAdjustmentBilling to see how much of this adjustment has already been invoiced
                BigDecimal adjAlreadyInvoicedAmount = null;
                try {
                    Map<String, Object> checkResult = dispatcher.runSync("calculateInvoicedAdjustmentTotal",
                            UtilMisc.toMap("orderAdjustment", adj));
                    adjAlreadyInvoicedAmount = (BigDecimal) checkResult.get("invoicedTotal");
                } catch (GenericServiceException e) {
                    Debug.logError(e, "Accounting trouble calling calculateInvoicedAdjustmentTotal service",
                            module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                            "AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale));
                }

                //                    if (adj.get("amount") == null) { TODO check usage with webPos. Was: fix a bug coming from POS in case of use of a discount (on item(s) or sale, item(s) here) and a cash amount higher than total (hence issuing change)
                //                        continue;
                //                    }
                // Set adjustment amount as amountAlreadyIncluded to continue invoice item creation process
                Boolean isTaxIncludedInPrice = adj.getString("orderAdjustmentTypeId").equals("VAT_TAX")
                        && UtilValidate.isNotEmpty(adj.getBigDecimal("amountAlreadyIncluded"))
                        && adj.getBigDecimal("amountAlreadyIncluded").signum() != 0;
                if ((adj.getBigDecimal("amount").signum() == 0) && isTaxIncludedInPrice) {
                    adj.set("amount", adj.getBigDecimal("amountAlreadyIncluded"));
                }
                // If the absolute invoiced amount >= the abs of the adjustment amount, the full amount has already been invoiced, so skip this adjustment
                if (adjAlreadyInvoicedAmount.abs().compareTo(
                        adj.getBigDecimal("amount").setScale(invoiceTypeDecimals, ROUNDING).abs()) > 0) {
                    continue;
                }

                BigDecimal originalOrderItemQuantity = OrderReadHelper.getOrderItemQuantity(originalOrderItem);
                BigDecimal amount = ZERO;
                if (originalOrderItemQuantity.signum() != 0) {
                    if (adj.get("amount") != null) {
                        if ("PROMOTION_ADJUSTMENT".equals(adj.getString("orderAdjustmentTypeId"))
                                && adj.get("productPromoId") != null) {
                            /* Find negative amountAlreadyIncluded in OrderAdjustment to subtract it from discounted amount.
                                                                  As we stored negative sales tax amount in order adjustment for discounted item.
                             */
                            List<EntityExpr> exprs = UtilMisc.toList(
                                    EntityCondition.makeCondition("orderId", EntityOperator.EQUALS,
                                            orderItem.getString("orderId")),
                                    EntityCondition.makeCondition("orderItemSeqId", EntityOperator.EQUALS,
                                            orderItem.getString("orderItemSeqId")),
                                    EntityCondition.makeCondition("orderAdjustmentTypeId",
                                            EntityOperator.EQUALS, "VAT_TAX"),
                                    EntityCondition.makeCondition("amountAlreadyIncluded",
                                            EntityOperator.LESS_THAN, BigDecimal.ZERO));
                            EntityCondition andCondition = EntityCondition.makeCondition(exprs,
                                    EntityOperator.AND);
                            GenericValue orderAdjustment = EntityUtil.getFirst(delegator
                                    .findList("OrderAdjustment", andCondition, null, null, null, false));
                            if (UtilValidate.isNotEmpty(orderAdjustment)) {
                                amount = adj.getBigDecimal("amount")
                                        .subtract(orderAdjustment.getBigDecimal("amountAlreadyIncluded"))
                                        .setScale(100, ROUNDING);
                            } else {
                                amount = adj.getBigDecimal("amount");
                            }
                        } else {
                            // pro-rate the amount
                            // set decimals = 100 means we don't round this intermediate value, which is very important
                            if (isTaxIncludedInPrice) {
                                BigDecimal priceWithTax = originalOrderItem.getBigDecimal("unitPrice");
                                // Get tax included in item price
                                amount = priceWithTax.subtract(billingAmount);
                                amount = amount.multiply(billingQuantity);
                                // get adjustment amount
                                /* Get tax amount of other invoice and calculate remaining amount need to store in invoice item(Handle case of of partial shipment and promotional item)
                                                                      to adjust tax amount in invoice item. 
                                 */
                                BigDecimal otherInvoiceTaxAmount = BigDecimal.ZERO;
                                GenericValue orderAdjBilling = EntityUtil.getFirst(delegator.findByAnd(
                                        "OrderAdjustmentBilling",
                                        UtilMisc.toMap("orderAdjustmentId", adj.getString("orderAdjustmentId")),
                                        null, false));
                                if (UtilValidate.isNotEmpty(orderAdjBilling)) {
                                    List<GenericValue> invoiceItems = delegator.findByAnd("InvoiceItem",
                                            UtilMisc.toMap("invoiceId", orderAdjBilling.getString("invoiceId"),
                                                    "invoiceItemTypeId", "ITM_SALES_TAX", "productId",
                                                    originalOrderItem.getString("productId")),
                                            null, isTaxIncludedInPrice);
                                    for (GenericValue invoiceItem : invoiceItems) {
                                        otherInvoiceTaxAmount = otherInvoiceTaxAmount
                                                .add(invoiceItem.getBigDecimal("amount"));
                                    }
                                    if (otherInvoiceTaxAmount.compareTo(BigDecimal.ZERO) > 0) {
                                        BigDecimal remainingAmount = adj.getBigDecimal("amountAlreadyIncluded")
                                                .subtract(otherInvoiceTaxAmount);
                                        amount = amount.min(remainingAmount);
                                    }
                                }
                                amount = amount.min(adj.getBigDecimal("amountAlreadyIncluded")).setScale(100,
                                        ROUNDING);
                            } else {
                                amount = adj.getBigDecimal("amount").divide(originalOrderItemQuantity, 100,
                                        ROUNDING);
                                amount = amount.multiply(billingQuantity);
                            }
                        }
                        // Tax needs to be rounded differently from other order adjustments
                        if (adj.getString("orderAdjustmentTypeId").equals("SALES_TAX")) {
                            amount = amount.setScale(TAX_DECIMALS, TAX_ROUNDING);
                        } else {
                            amount = amount.setScale(invoiceTypeDecimals, ROUNDING);
                        }
                    } else if (adj.get("sourcePercentage") != null) {
                        // pro-rate the amount
                        // set decimals = 100 means we don't round this intermediate value, which is very important
                        BigDecimal percent = adj.getBigDecimal("sourcePercentage");
                        percent = percent.divide(new BigDecimal(100), 100, ROUNDING);
                        amount = billingAmount.multiply(percent);
                        amount = amount.divide(originalOrderItemQuantity, 100, ROUNDING);
                        amount = amount.multiply(billingQuantity);
                        amount = amount.setScale(invoiceTypeDecimals, ROUNDING);
                    }
                }
                if (amount.signum() != 0) {
                    Map<String, Object> createInvoiceItemAdjContext = new HashMap<String, Object>();
                    createInvoiceItemAdjContext.put("invoiceId", invoiceId);
                    createInvoiceItemAdjContext.put("invoiceItemSeqId", invoiceItemSeqId);
                    createInvoiceItemAdjContext.put("invoiceItemTypeId", getInvoiceItemType(delegator,
                            adj.getString("orderAdjustmentTypeId"), null, invoiceType, "INVOICE_ITM_ADJ"));
                    createInvoiceItemAdjContext.put("quantity", BigDecimal.ONE);
                    createInvoiceItemAdjContext.put("amount", amount);
                    createInvoiceItemAdjContext.put("productId", orderItem.get("productId"));
                    createInvoiceItemAdjContext.put("productFeatureId", orderItem.get("productFeatureId"));
                    createInvoiceItemAdjContext.put("overrideGlAccountId", adj.get("overrideGlAccountId"));
                    createInvoiceItemAdjContext.put("parentInvoiceId", invoiceId);
                    createInvoiceItemAdjContext.put("parentInvoiceItemSeqId", parentInvoiceItemSeqId);
                    createInvoiceItemAdjContext.put("userLogin", userLogin);
                    createInvoiceItemAdjContext.put("taxAuthPartyId", adj.get("taxAuthPartyId"));
                    createInvoiceItemAdjContext.put("taxAuthGeoId", adj.get("taxAuthGeoId"));
                    createInvoiceItemAdjContext.put("taxAuthorityRateSeqId", adj.get("taxAuthorityRateSeqId"));

                    // some adjustments fill out the comments field instead
                    String description = (UtilValidate.isEmpty(adj.getString("description"))
                            ? adj.getString("comments")
                            : adj.getString("description"));
                    createInvoiceItemAdjContext.put("description", description);

                    // invoice items for sales tax are not taxable themselves
                    // TODO: This is not an ideal solution. Instead, we need to use OrderAdjustment.includeInTax when it is implemented
                    if (!(adj.getString("orderAdjustmentTypeId").equals("SALES_TAX"))) {
                        createInvoiceItemAdjContext.put("taxableFlag", product.get("taxable"));
                    }

                    // If the OrderAdjustment is associated to a ProductPromo,
                    // and the field ProductPromo.overrideOrgPartyId is set,
                    // copy the value to InvoiceItem.overrideOrgPartyId: this
                    // represent an organization override for the payToPartyId
                    if (UtilValidate.isNotEmpty(adj.getString("productPromoId"))) {
                        try {
                            GenericValue productPromo = adj.getRelatedOne("ProductPromo", false);
                            if (UtilValidate.isNotEmpty(productPromo.getString("overrideOrgPartyId"))) {
                                createInvoiceItemAdjContext.put("overrideOrgPartyId",
                                        productPromo.getString("overrideOrgPartyId"));
                            }
                        } catch (GenericEntityException e) {
                            Debug.logError(e, "Error looking up ProductPromo with id ["
                                    + adj.getString("productPromoId") + "]", module);
                        }
                    }

                    Map<String, Object> createInvoiceItemAdjResult = dispatcher.runSync("createInvoiceItem",
                            createInvoiceItemAdjContext);
                    if (ServiceUtil.isError(createInvoiceItemAdjResult)) {
                        return ServiceUtil.returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingInvoiceItemFromOrder", locale),
                                null, null, createInvoiceItemAdjResult);
                    }

                    // Create the OrderAdjustmentBilling record
                    Map<String, Object> createOrderAdjustmentBillingContext = new HashMap<String, Object>();
                    createOrderAdjustmentBillingContext.put("orderAdjustmentId",
                            adj.getString("orderAdjustmentId"));
                    createOrderAdjustmentBillingContext.put("invoiceId", invoiceId);
                    createOrderAdjustmentBillingContext.put("invoiceItemSeqId", invoiceItemSeqId);
                    createOrderAdjustmentBillingContext.put("amount", amount);
                    createOrderAdjustmentBillingContext.put("userLogin", userLogin);

                    Map<String, Object> createOrderAdjustmentBillingResult = dispatcher
                            .runSync("createOrderAdjustmentBilling", createOrderAdjustmentBillingContext);
                    if (ServiceUtil.isError(createOrderAdjustmentBillingResult)) {
                        return ServiceUtil.returnError(
                                UtilProperties.getMessage(resource,
                                        "AccountingErrorCreatingOrderAdjustmentBillingFromOrder", locale),
                                null, null, createOrderAdjustmentBillingContext);
                    }

                    // this adjustment amount
                    BigDecimal thisAdjAmount = amount;

                    // adjustments only apply to totals when they are not tax or shipping adjustments
                    if (!"SALES_TAX".equals(adj.getString("orderAdjustmentTypeId"))
                            && !"SHIPPING_ADJUSTMENT".equals(adj.getString("orderAdjustmentTypeId"))) {
                        // increment the invoice subtotal
                        invoiceSubTotal = invoiceSubTotal.add(thisAdjAmount).setScale(100, ROUNDING);

                        // add to the ship amount only if it applies to this item
                        if (shippingApplies) {
                            invoiceShipProRateAmount = invoiceShipProRateAmount.add(thisAdjAmount)
                                    .setScale(invoiceTypeDecimals, ROUNDING);
                        }
                    }

                    // increment the counter
                    invoiceItemSeqNum++;
                    invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                            INVOICE_ITEM_SEQUENCE_ID_DIGITS);
                }
            }
        }

        // create header adjustments as line items -- always to tax/shipping last
        Map<GenericValue, BigDecimal> shipAdjustments = new HashMap<GenericValue, BigDecimal>();
        Map<GenericValue, BigDecimal> taxAdjustments = new HashMap<GenericValue, BigDecimal>();

        List<GenericValue> headerAdjustments = orh.getOrderHeaderAdjustments();
        for (GenericValue adj : headerAdjustments) {

            // Check against OrderAdjustmentBilling to see how much of this adjustment has already been invoiced
            BigDecimal adjAlreadyInvoicedAmount = null;
            try {
                Map<String, Object> checkResult = dispatcher.runSync("calculateInvoicedAdjustmentTotal",
                        UtilMisc.toMap("orderAdjustment", adj));
                adjAlreadyInvoicedAmount = ((BigDecimal) checkResult.get("invoicedTotal"))
                        .setScale(invoiceTypeDecimals, ROUNDING);
            } catch (GenericServiceException e) {
                Debug.logError(e, "Accounting trouble calling calculateInvoicedAdjustmentTotal service",
                        module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                        "AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale));
            }

            //                if (null == adj.get("amount")) { TODO check usage with webPos. Was: fix a bug coming from POS in case of use of a discount (on item(s) or sale, sale here) and a cash amount higher than total (hence issuing change)
            //                    continue;
            //                }
            // If the absolute invoiced amount >= the abs of the adjustment amount, the full amount has already been invoiced, so skip this adjustment
            if (adjAlreadyInvoicedAmount.abs().compareTo(
                    adj.getBigDecimal("amount").setScale(invoiceTypeDecimals, ROUNDING).abs()) >= 0) {
                continue;
            }

            if ("SHIPPING_CHARGES".equals(adj.getString("orderAdjustmentTypeId"))) {
                shipAdjustments.put(adj, adjAlreadyInvoicedAmount);
            } else if ("SALES_TAX".equals(adj.getString("orderAdjustmentTypeId"))) {
                taxAdjustments.put(adj, adjAlreadyInvoicedAmount);
            } else {
                // these will effect the shipping pro-rate (unless commented)
                // other adjustment type
                BigDecimal divisor = orderSubTotal;
                BigDecimal multiplier = invoiceSubTotal;
                if (BigDecimal.ZERO.compareTo(multiplier) == 0 && BigDecimal.ZERO.compareTo(divisor) == 0) {
                    // if multiplier and divisor are equal to zero then use the quantities instead of the amounts
                    // this is useful when the order has free items and misc charges
                    divisor = orderQuantity;
                    multiplier = invoiceQuantity;
                }

                calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, divisor, multiplier,
                        adj.getBigDecimal("amount").setScale(invoiceTypeDecimals, ROUNDING),
                        invoiceTypeDecimals, ROUNDING, userLogin, dispatcher, locale);
                // invoiceShipProRateAmount += adjAmount;
                // do adjustments compound or are they based off subtotal? Here we will (unless commented)
                // invoiceSubTotal += adjAmount;

                // increment the counter
                invoiceItemSeqNum++;
                invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                        INVOICE_ITEM_SEQUENCE_ID_DIGITS);
            }
        }

        // next do the shipping adjustments.  Note that we do not want to add these to the invoiceSubTotal or orderSubTotal for pro-rating tax later, as that would cause
        // numerator/denominator problems when the shipping is not pro-rated but rather charged all on the first invoice
        for (GenericValue adj : shipAdjustments.keySet()) {
            BigDecimal adjAlreadyInvoicedAmount = shipAdjustments.get(adj);

            if ("N".equalsIgnoreCase(prorateShipping)) {

                // Set the divisor and multiplier to 1 to avoid prorating
                BigDecimal divisor = BigDecimal.ONE;
                BigDecimal multiplier = BigDecimal.ONE;

                // The base amount in this case is the adjustment amount minus the total already invoiced for that adjustment, since
                //  it won't be prorated
                BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(invoiceTypeDecimals, ROUNDING)
                        .subtract(adjAlreadyInvoicedAmount);
                calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, divisor, multiplier,
                        baseAmount, invoiceTypeDecimals, ROUNDING, userLogin, dispatcher, locale);
            } else {

                // Pro-rate the shipping amount based on shippable information
                BigDecimal divisor = shippableAmount;
                BigDecimal multiplier = invoiceShipProRateAmount;
                if (BigDecimal.ZERO.compareTo(multiplier) == 0 && BigDecimal.ZERO.compareTo(divisor) == 0) {
                    // if multiplier and divisor are equal to zero then use the quantities instead of the amounts
                    // this is useful when the order has free items and shipping charges
                    divisor = shippableQuantity;
                    multiplier = invoiceShippableQuantity;
                }

                // The base amount in this case is the adjustment amount, since we want to prorate based on the full amount
                BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(invoiceTypeDecimals, ROUNDING);
                calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, divisor, multiplier,
                        baseAmount, invoiceTypeDecimals, ROUNDING, userLogin, dispatcher, locale);
            }

            // Increment the counter
            invoiceItemSeqNum++;
            invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                    INVOICE_ITEM_SEQUENCE_ID_DIGITS);
        }

        // last do the tax adjustments
        String prorateTaxes = productStore != null ? productStore.getString("prorateTaxes") : "Y";
        if (prorateTaxes == null) {
            prorateTaxes = "Y";
        }
        for (Map.Entry<GenericValue, BigDecimal> entry : taxAdjustments.entrySet()) {
            GenericValue adj = entry.getKey();
            BigDecimal adjAlreadyInvoicedAmount = entry.getValue();
            BigDecimal adjAmount = null;

            if ("N".equalsIgnoreCase(prorateTaxes)) {

                // Set the divisor and multiplier to 1 to avoid prorating
                BigDecimal divisor = BigDecimal.ONE;
                BigDecimal multiplier = BigDecimal.ONE;

                // The base amount in this case is the adjustment amount minus the total already invoiced for that adjustment, since
                //  it won't be prorated
                BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(TAX_DECIMALS, TAX_ROUNDING)
                        .subtract(adjAlreadyInvoicedAmount);
                adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, divisor,
                        multiplier, baseAmount, TAX_DECIMALS, TAX_ROUNDING, userLogin, dispatcher, locale);
            } else {

                // Pro-rate the tax amount based on shippable information
                BigDecimal divisor = orderSubTotal;
                BigDecimal multiplier = invoiceSubTotal;

                // The base amount in this case is the adjustment amount, since we want to prorate based on the full amount
                BigDecimal baseAmount = adj.getBigDecimal("amount");
                adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, divisor,
                        multiplier, baseAmount, TAX_DECIMALS, TAX_ROUNDING, userLogin, dispatcher, locale);
            }
            invoiceSubTotal = invoiceSubTotal.add(adjAmount).setScale(invoiceTypeDecimals, ROUNDING);

            // Increment the counter
            invoiceItemSeqNum++;
            invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum,
                    INVOICE_ITEM_SEQUENCE_ID_DIGITS);
        }

        // check for previous order payments
        List<GenericValue> orderPaymentPrefs = EntityQuery.use(delegator).from("OrderPaymentPreference").where(
                EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderId),
                EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_CANCELLED"))
                .queryList();
        List<GenericValue> currentPayments = new LinkedList<GenericValue>();
        for (GenericValue paymentPref : orderPaymentPrefs) {
            List<GenericValue> payments = paymentPref.getRelated("Payment", null, null, false);
            currentPayments.addAll(payments);
        }
        // apply these payments to the invoice if they have any remaining amount to apply
        for (GenericValue payment : currentPayments) {
            if ("PMNT_VOID".equals(payment.getString("statusId"))
                    || "PMNT_CANCELLED".equals(payment.getString("statusId"))) {
                continue;
            }
            BigDecimal notApplied = PaymentWorker.getPaymentNotApplied(payment);
            if (notApplied.signum() > 0) {
                Map<String, Object> appl = new HashMap<String, Object>();
                appl.put("paymentId", payment.get("paymentId"));
                appl.put("invoiceId", invoiceId);
                appl.put("billingAccountId", billingAccountId);
                appl.put("amountApplied", notApplied);
                appl.put("userLogin", userLogin);
                Map<String, Object> createPayApplResult = dispatcher.runSync("createPaymentApplication", appl);
                if (ServiceUtil.isError(createPayApplResult)) {
                    return ServiceUtil
                            .returnError(
                                    UtilProperties.getMessage(resource,
                                            "AccountingErrorCreatingInvoiceFromOrder", locale),
                                    null, null, createPayApplResult);
                }
            }
        }

        // Should all be in place now. Depending on the ProductStore.autoApproveInvoice setting, set status to INVOICE_READY (unless it's a purchase invoice, which we set to INVOICE_IN_PROCESS)
        String autoApproveInvoice = productStore != null ? productStore.getString("autoApproveInvoice") : "Y";
        if (!"N".equals(autoApproveInvoice)) {
            String nextStatusId = "PURCHASE_INVOICE".equals(invoiceType) ? "INVOICE_IN_PROCESS"
                    : "INVOICE_READY";
            Map<String, Object> setInvoiceStatusResult = dispatcher.runSync("setInvoiceStatus",
                    UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "statusId", nextStatusId,
                            "userLogin", userLogin));
            if (ServiceUtil.isError(setInvoiceStatusResult)) {
                return ServiceUtil.returnError(
                        UtilProperties.getMessage(resource, "AccountingErrorCreatingInvoiceFromOrder", locale),
                        null, null, setInvoiceStatusResult);
            }
        }

        Map<String, Object> resp = ServiceUtil.returnSuccess();
        resp.put("invoiceId", invoiceId);
        resp.put("invoiceTypeId", invoiceType);
        return resp;
    } catch (GenericEntityException e) {
        Debug.logError(e, "Entity/data problem creating invoice from order items: " + e.toString(), module);
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingEntityDataProblemCreatingInvoiceFromOrderItems",
                        UtilMisc.toMap("reason", e.toString()), locale));
    } catch (GenericServiceException e) {
        Debug.logError(e, "Service/other problem creating invoice from order items: " + e.toString(), module);
        return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                "AccountingServiceOtherProblemCreatingInvoiceFromOrderItems",
                UtilMisc.toMap("reason", e.toString()), locale));
    }
}

From source file:org.openbravo.erpCommon.ad_forms.AcctServer.java

public BigDecimal convertAmount(BigDecimal _amount, boolean isReceipt, String dateAcct, String table_ID,
        String record_ID, String currencyIDFrom, String currencyIDTo, DocLine line, AcctSchema as, Fact fact,
        String Fact_Acct_Group_ID, String seqNo, ConnectionProvider conn, boolean bookDifferences)
        throws ServletException {
    BigDecimal amtDiff = BigDecimal.ZERO;
    if (_amount == null || _amount.compareTo(BigDecimal.ZERO) == 0) {
        return _amount;
    }//from   w  w w  . ja v  a 2  s . c o m
    String conversionDate = dateAcct;
    String strDateFormat = OBPropertiesProvider.getInstance().getOpenbravoProperties()
            .getProperty("dateFormat.java");
    final SimpleDateFormat dateFormat = new SimpleDateFormat(strDateFormat);
    ConversionRateDoc conversionRateDoc = getConversionRateDoc(table_ID, record_ID, currencyIDFrom,
            currencyIDTo);
    BigDecimal amtFrom = BigDecimal.ZERO;
    BigDecimal amtFromSourcecurrency = BigDecimal.ZERO;
    BigDecimal amtTo = BigDecimal.ZERO;
    if (table_ID.equals(TABLEID_Invoice)) {
        Invoice invoice = OBDal.getInstance().get(Invoice.class, record_ID);
        conversionDate = dateFormat.format(invoice.getAccountingDate());
    } else if (table_ID.equals(TABLEID_Payment)) {
        FIN_Payment payment = OBDal.getInstance().get(FIN_Payment.class, record_ID);
        conversionDate = dateFormat.format(payment.getPaymentDate());
    } else if (table_ID.equals(TABLEID_Transaction)) {
        FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class, record_ID);
        conversionDate = dateFormat.format(transaction.getDateAcct());
    }
    if (conversionRateDoc != null && record_ID != null) {
        amtFrom = applyRate(_amount, conversionRateDoc, true);
    } else {
        // I try to find a reversal rate for the doc, if exists i apply it reversal as well
        conversionRateDoc = getConversionRateDoc(table_ID, record_ID, currencyIDTo, currencyIDFrom);
        if (conversionRateDoc != null) {
            amtFrom = applyRate(_amount, conversionRateDoc, false);
        } else {
            String convertedAmt = getConvertedAmt(_amount.toString(), currencyIDFrom, currencyIDTo,
                    conversionDate, "", AD_Client_ID, AD_Org_ID, conn);
            if (convertedAmt != null && !"".equals(convertedAmt)) {
                amtFrom = new BigDecimal(convertedAmt);
            } else {
                throw new OBException("@NotConvertible@");
            }
        }
    }
    ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID, currencyIDFrom,
            currencyIDTo);
    if (AD_Table_ID.equals(TABLEID_Invoice)) {
        Invoice invoice = OBDal.getInstance().get(Invoice.class, Record_ID);
        conversionDate = dateFormat.format(invoice.getAccountingDate());
    } else if (AD_Table_ID.equals(TABLEID_Payment)) {
        FIN_Payment payment = OBDal.getInstance().get(FIN_Payment.class, Record_ID);
        conversionDate = dateFormat.format(payment.getPaymentDate());
    } else if (AD_Table_ID.equals(TABLEID_Transaction) || AD_Table_ID.equals(TABLEID_Reconciliation)) {
        String transactionID = Record_ID;
        // When TableID= Reconciliation info is loaded from transaction
        if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                && line instanceof DocLine_FINReconciliation) {
            transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
        }
        FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class, transactionID);
        conversionDate = dateFormat.format(transaction.getDateAcct());
        conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transaction.getId(),
                currencyIDFrom, currencyIDTo);
    } else {
        conversionDate = dateAcct;
    }
    if (conversionRateCurrentDoc != null) {
        amtTo = applyRate(_amount, conversionRateCurrentDoc, true);
        amtFromSourcecurrency = applyRate(amtFrom, conversionRateCurrentDoc, false);
    } else {
        // I try to find a reversal rate for the doc, if exists i apply it reversal as well
        if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                && line instanceof DocLine_FINReconciliation) {
            String transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
            conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transactionID, currencyIDTo,
                    currencyIDFrom);
        } else {
            conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID, currencyIDTo,
                    currencyIDFrom);
        }
        if (conversionRateCurrentDoc != null) {
            amtTo = applyRate(_amount, conversionRateCurrentDoc, false);
            amtFromSourcecurrency = applyRate(amtFrom, conversionRateCurrentDoc, true);
        } else {
            String convertedAmt = getConvertedAmt(_amount.toString(), currencyIDFrom, currencyIDTo,
                    conversionDate, "", AD_Client_ID, AD_Org_ID, conn);
            if (convertedAmt != null && !"".equals(convertedAmt)) {
                amtTo = new BigDecimal(convertedAmt);
            } else {
                throw new OBException("@NotConvertible@");
            }
            if (amtTo.compareTo(BigDecimal.ZERO) != 0)
                amtFromSourcecurrency = amtFrom.multiply(_amount).divide(amtTo, conversionRatePrecision,
                        BigDecimal.ROUND_HALF_EVEN);
            else
                amtFromSourcecurrency = amtFrom;
        }
    }
    amtDiff = (amtTo).subtract(amtFrom);
    // Add differences related to Different rates for accounting among currencies
    // _amount * ((TrxRate *
    // AccountingRateCurrencyFromCurrencyTo)-AccountingRateCurrencyDocCurrencyTo)
    amtDiff = amtDiff.add(calculateMultipleRatesDifferences(_amount, currencyIDFrom, currencyIDTo, line, conn));
    Currency currencyTo = OBDal.getInstance().get(Currency.class, currencyIDTo);
    amtDiff = amtDiff.setScale(currencyTo.getStandardPrecision().intValue(), BigDecimal.ROUND_HALF_EVEN);
    if (bookDifferences) {
        if ((!isReceipt && amtDiff.compareTo(BigDecimal.ZERO) == 1)
                || (isReceipt && amtDiff.compareTo(BigDecimal.ZERO) == -1)) {
            fact.createLine(line, getAccount(AcctServer.ACCTTYPE_ConvertGainDefaultAmt, as, conn), currencyIDTo,
                    "", amtDiff.abs().toString(), Fact_Acct_Group_ID, seqNo, DocumentType, conn);
        } else if (amtDiff.compareTo(BigDecimal.ZERO) != 0) {
            fact.createLine(line, getAccount(AcctServer.ACCTTYPE_ConvertChargeDefaultAmt, as, conn),
                    currencyIDTo, amtDiff.abs().toString(), "", Fact_Acct_Group_ID, seqNo, DocumentType, conn);
        } else {
            return amtFromSourcecurrency;
        }
    }
    if (log4j.isDebugEnabled())
        log4j.debug("Amt from: " + amtFrom + "[" + currencyIDFrom + "]" + " Amt to: " + amtTo + "["
                + currencyIDTo + "] - amtFromSourcecurrency: " + amtFromSourcecurrency);
    // return value in original currency
    return amtFromSourcecurrency;
}

From source file:org.ofbiz.order.order.OrderServices.java

public static BigDecimal calculatePurchaseOrderTermValue(DispatchContext ctx,
        Map<String, ? extends Object> context) {
    BigDecimal termAmount = BigDecimal.ZERO;
    BigDecimal basicAmount = (BigDecimal) context.get("basicAmount");
    BigDecimal poValue = (BigDecimal) context.get("poValue");
    BigDecimal exciseDuty = (BigDecimal) context.get("exciseDuty");
    String termTypeId = (String) context.get("termTypeId");
    String uomId = (String) context.get("uomId");
    BigDecimal termValue = (BigDecimal) context.get("termValue");

    if (UtilValidate.isEmpty(termTypeId)) {
        return termAmount;
    }/*from  w ww  .  j a  v a2  s  . c o  m*/
    //this to handle non derived terms
    termAmount = termValue;

    //Discount Before ED
    if (termTypeId.equals("COGS_DISC")) {
        if (UtilValidate.isNotEmpty(uomId) && uomId.equals("PERCENT")) {
            termAmount = ((basicAmount.add(exciseDuty)).multiply(termValue)).divide(new BigDecimal("100"),
                    taxRounding);
            termAmount = termAmount.negate();
        } else {
            termAmount = termValue.negate();
        }
    }

    //Discount  After Tax
    if (termTypeId.equals("COGS_DISC_ATR")) {
        if (UtilValidate.isNotEmpty(uomId) && uomId.equals("PERCENT")) {
            Debug.log("poValue========" + poValue);
            termAmount = (poValue.multiply(termValue)).divide(new BigDecimal("100"), taxRounding);
            termAmount = termAmount.negate();
        } else {
            termAmount = termValue.negate();
        }
    }
    //Packing And Forwarding Charges Before Tax
    if (termTypeId.equals("COGS_PCK_FWD")) {
        if (UtilValidate.isNotEmpty(uomId) && uomId.equals("PERCENT")) {
            termAmount = ((basicAmount.add(exciseDuty)).multiply(termValue)).divide(new BigDecimal("100"),
                    taxRounding);
        } else {
            termAmount = termValue;
        }
    }
    //Packing And Forwarding Charges After Tax
    if (termTypeId.equals("COGS_PCK_FWD_ATR")) {
        if (UtilValidate.isNotEmpty(uomId) && uomId.equals("PERCENT")) {
            Debug.log("poValue========" + poValue);
            termAmount = (poValue.multiply(termValue)).divide(new BigDecimal("100"), taxRounding);
        } else {
            termAmount = termValue;
        }
    }
    if (termTypeId.equals("COGS_INSURANCE")) {
        if (UtilValidate.isNotEmpty(uomId) && uomId.equals("PERCENT")) {
            termAmount = ((basicAmount.add(exciseDuty)).multiply(termValue)).divide(new BigDecimal("100"),
                    taxRounding);
        } else {
            termAmount = termValue;
        }
    }

    return termAmount;
}

From source file:com.turborep.turbotracker.banking.service.BankingServiceImpl.java

@Override
public Integer createtransactionBanknewCheck(MoAccount moAccount, Motransaction M1, String DepositType,
        Integer yearID, Integer periodID, String userName, BigDecimal balance, boolean accountStatus,
        int motransiid, String oper, String gridData, boolean futureornot, BigDecimal currentbalance,
        BigDecimal oldamount, String NewMoTypeId, BigDecimal amt, String aMemo, String aRxMasterID)
        throws BankingException, CompanyException {
    Transaction aTransaction;/* w w  w . j a  v  a2  s.  c om*/
    Session aSession = null;
    aSession = itsSessionFactory.openSession();
    aTransaction = aSession.beginTransaction();
    try {

        aTransaction.begin();

        if (oper.equals("new")) {
            updateDepositAndWithDraw(moAccount, aSession);
            M1.setBalance(balance);
            motransiid = addTransactionDetails(M1, aSession, "new");
            M1.setMoTransactionId(motransiid);
            if (accountStatus)
                gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName, aSession);
        } else if (oper.equals("add")) {
            Momultipleaccount momulaccount = null;
            BigDecimal TotalAmt = new BigDecimal(0);

            updateDepositAndWithDraw(moAccount, aSession);
            M1.setBalance(balance);
            motransiid = addTransactionDetails(M1, aSession, "new");
            M1.setMoTransactionId(motransiid);
            if (accountStatus) {
                gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName, aSession);
            } else {

                JsonParser parser = new JsonParser();
                if (null != gridData && gridData.length() > 6) {
                    JsonElement ele = parser.parse(gridData);
                    JsonArray array = ele.getAsJsonArray();
                    System.out.println("array length==>" + array.size());
                    for (JsonElement ele1 : array) {

                        momulaccount = new Momultipleaccount();
                        JsonObject obj = ele1.getAsJsonObject();

                        momulaccount.setCoAccountId(obj.get("coAccountId").getAsInt());
                        M1.setCoAccountId(obj.get("coAccountId").getAsInt());

                        momulaccount.setAmount(obj.get("amount").getAsBigDecimal());
                        M1.setAmount(obj.get("amount").getAsBigDecimal());

                        momulaccount.setMoTransactionId(motransiid);
                        momulaccount.setMoMultipleAccountsId(obj.get("moMultipleAccountsId").getAsInt());
                        System.out.println("checkupdates" + momulaccount.getCoAccountId() + "=="
                                + momulaccount.getAmount() + "==" + obj.get("moMultipleAccountsId").getAsInt());
                        if (obj.get("moMultipleAccountsId").getAsInt() == 0) {
                            saveGlmultipleAccount1(momulaccount, aSession);
                        } else {
                            updateGlmultipleAccount1(momulaccount, aSession);
                        }
                        DepositType = "Multiple with subaccounts";
                        gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName,
                                aSession);

                        TotalAmt = TotalAmt.add(obj.get("amount").getAsBigDecimal());
                    }
                    DepositType = "Multiple with mainaccounts";
                    M1.setAmount(TotalAmt);
                    gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName, aSession);

                }

            }

        } else if (oper.equals("edit")) {
            Momultipleaccount momulaccount = null;
            BigDecimal TotalAmt = new BigDecimal(0);

            updateTransactionDetails1(M1, aSession);
            Coledgersource aColedgersource = gltransactionService.getColedgersourceDetail("BT");

            GlRollback glRollback = new GlRollback();
            glRollback.setVeBillID(M1.getMoTransactionId());
            glRollback.setCoLedgerSourceID(aColedgersource.getCoLedgerSourceId());
            glRollback.setPeriodID(periodID);
            glRollback.setYearID(yearID);
            glRollback.setTransactionDate(M1.getTransactionDate());
            gltransactionService.rollBackGlTransaction1(glRollback, aSession);

            String aDescription = M1.getDescription();
            String aReference = M1.getReference();
            if (M1.getMoTransactionTypeId() == 0) {
                /*if(futureornot){
                balance=currentbalance.subtract(oldamount);
                }else{
                balance=currentbalance;
                }*/
                balance = currentbalance.subtract(oldamount);
                oldamount = oldamount.multiply(new BigDecimal(-1));
                short change = 1;
                M1.setMoTransactionTypeId(change);
                moAccount.setSubtractions(oldamount); // 220
            } else {

                /*if(futureornot){
                balance=currentbalance.add(oldamount);
                }else{
                   balance=currentbalance;
                }*/
                balance = currentbalance.add(oldamount);
                short change = 0;
                M1.setMoTransactionTypeId(change);
                moAccount.setAdditions(oldamount);
            }
            moAccount.setMoTransactionTypeId(M1.getMoTransactionTypeId());
            updateDepositAndWithDraw(moAccount, aSession);

            M1.setAmount(oldamount);
            M1.setBalance(balance);

            addTransactionDetails(M1, aSession, "rollback");

            BigDecimal newbalance = new BigDecimal("0.00");
            short editmotypeid = Short.parseShort(NewMoTypeId);
            M1.setMoTransactionTypeId(editmotypeid);
            M1.setAmount(amt);
            M1.setStatus(false);
            if (M1.getMoTransactionTypeId() == 0) {
                if (M1.getAmount().doubleValue() < 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                /*if(futureornot){
                   newbalance=balance.add(M1.getAmount());
                   }else{
                   newbalance=currentbalance;
                   }*/
                newbalance = balance.add(M1.getAmount());
                moAccount.setAdditions(M1.getAmount());

            } else {
                if (M1.getAmount().doubleValue() > 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                /*if(futureornot){
                   newbalance=balance.add(M1.getAmount());
                   }else{
                   newbalance=currentbalance;
                   }*/
                newbalance = balance.add(M1.getAmount());
                moAccount.setSubtractions(M1.getAmount());
            }
            M1.setBalance(newbalance);
            moAccount.setMoTransactionTypeId(M1.getMoTransactionTypeId());
            updateDepositAndWithDraw(moAccount, aSession);

            if (editmotypeid == 2) {
                M1.setMemo(aMemo);
                M1.setRxMasterId(Integer.parseInt(aRxMasterID));
            }

            M1.setDescription(aDescription);
            M1.setReference(aReference);
            motransiid = addTransactionDetails(M1, aSession, "new");
            M1.setMoTransactionId(motransiid);
            if (accountStatus == true) {
                gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName, aSession);
            } else {
                JsonParser parser = new JsonParser();
                if (null != gridData && gridData.length() > 6) {

                    if ((oper.equals("edit") || oper.equals("delete"))) {

                        glRollback.setVeBillID(M1.getMoTransactionId());
                        glRollback.setCoLedgerSourceID(aColedgersource.getCoLedgerSourceId());
                        glRollback.setPeriodID(periodID);
                        glRollback.setYearID(yearID);
                        glRollback.setTransactionDate(M1.getTransactionDate());

                        gltransactionService.rollBackGlTransaction1(glRollback, aSession);
                    }

                    JsonElement ele = parser.parse(gridData);
                    JsonArray array = ele.getAsJsonArray();
                    System.out.println("array length==>" + array.size());
                    for (JsonElement ele1 : array) {

                        momulaccount = new Momultipleaccount();
                        JsonObject obj = ele1.getAsJsonObject();

                        momulaccount.setCoAccountId(obj.get("coAccountId").getAsInt());
                        M1.setCoAccountId(obj.get("coAccountId").getAsInt());

                        momulaccount.setAmount(obj.get("amount").getAsBigDecimal());
                        M1.setAmount(obj.get("amount").getAsBigDecimal());

                        momulaccount.setMoTransactionId(motransiid);
                        momulaccount.setMoMultipleAccountsId(obj.get("moMultipleAccountsId").getAsInt());
                        System.out.println("checkupdates" + momulaccount.getCoAccountId() + "=="
                                + momulaccount.getAmount() + "==" + obj.get("moMultipleAccountsId").getAsInt());
                        if (obj.get("moMultipleAccountsId").getAsInt() == 0) {
                            saveGlmultipleAccount1(momulaccount, aSession);
                        } else {
                            updateGlmultipleAccount1(momulaccount, aSession);
                        }
                        DepositType = "Multiple with subaccounts";
                        gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName,
                                aSession);

                        TotalAmt = TotalAmt.add(obj.get("amount").getAsBigDecimal());
                    }
                    DepositType = "Multiple with mainaccounts";
                    M1.setAmount(TotalAmt);
                    gltransactionService.bankingDeposits(M1, DepositType, yearID, periodID, userName, aSession);

                }
            }

        } else if (oper.equals("delete")) {
            updateTransactionDetails1(M1, aSession);
            Coledgersource aColedgersource = gltransactionService.getColedgersourceDetail("BT");

            GlRollback glRollback = new GlRollback();
            glRollback.setVeBillID(M1.getMoTransactionId());
            glRollback.setCoLedgerSourceID(aColedgersource.getCoLedgerSourceId());
            glRollback.setPeriodID(periodID);
            glRollback.setYearID(yearID);
            glRollback.setTransactionDate(new Date());

            gltransactionService.rollBackGlTransaction1(glRollback, aSession);
            balance = new BigDecimal("0.00");
            if (M1.getMoTransactionTypeId() == 0) {
                if (M1.getAmount().doubleValue() < 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                moAccount.setSubtractions(M1.getAmount());
                /*if(futureornot){
                   balance=currentbalance.add(M1.getAmount());
                   }else{
                   balance=currentbalance;
                   }*/
                balance = currentbalance.add(M1.getAmount());
            } else {
                if (M1.getAmount().doubleValue() > 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                moAccount.setAdditions(M1.getAmount());
                /*if(futureornot){
                   balance=currentbalance.add(M1.getAmount());
                   }else{
                   balance=currentbalance;
                   }*/
                balance = currentbalance.add(M1.getAmount());
            }
            moAccount.setOper(oper);
            updateDepositAndWithDraw(moAccount, aSession);
            M1.setStatus(true);
            M1.setBalance(balance);
            addTransactionDetails(M1, aSession, "rollback");
        } else if (oper.equals("void")) {
            boolean statusChk = true;
            statusChk = voidTransactionDetails1(M1, aSession);

            GlRollback glRollback = new GlRollback();

            if (statusChk) {
                Coledgersource aColedgersource = gltransactionService.getColedgersourceDetail("WC");
                glRollback.setVeBillID(Integer.parseInt(M1.getMoAccountId() + "" + M1.getReference()));
                glRollback.setCoLedgerSourceID(aColedgersource.getCoLedgerSourceId());
                glRollback.setPeriodID(periodID);
                glRollback.setYearID(yearID);
                glRollback.setTransactionDate(new Date());

                gltransactionService.rollBackGlTransaction1(glRollback, aSession);
            } else {
                Coledgersource aColedgersource = gltransactionService.getColedgersourceDetail("BT");

                glRollback.setVeBillID(M1.getMoTransactionId());
                glRollback.setCoLedgerSourceID(aColedgersource.getCoLedgerSourceId());
                glRollback.setPeriodID(periodID);
                glRollback.setYearID(yearID);
                glRollback.setTransactionDate(new Date());

                gltransactionService.rollBackGlTransaction1(glRollback, aSession);
            }

            balance = new BigDecimal("0.00");
            if (M1.getMoTransactionTypeId() == 0) {
                if (M1.getAmount().doubleValue() < 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                moAccount.setSubtractions(M1.getAmount());
                /*if(futureornot){
                   balance=currentbalance.add(M1.getAmount());
                   }else{
                   balance=currentbalance;
                   }*/
                balance = currentbalance.add(M1.getAmount());

            } else {
                if (M1.getAmount().doubleValue() < 0) {
                    M1.setAmount(M1.getAmount().multiply(new BigDecimal(-1)));
                }
                moAccount.setAdditions(M1.getAmount());
                /*if(futureornot){
                   balance=currentbalance.add(M1.getAmount());
                   }else{
                   balance=currentbalance;
                   }*/
                balance = currentbalance.add(M1.getAmount());
            }
            moAccount.setOper(oper);
            updateDepositAndWithDraw(moAccount, aSession);
            M1.setStatus(false);
            M1.setBalance(balance);
            M1.setDescription("[VOID]" + M1.getDescription());
            M1.setUniquechkRef(M1.getReference());
            addTransactionDetails(M1, aSession, "rollbackfromvoid");

        }
        aTransaction.commit();

    } catch (Exception e) {
        itsLogger.error(e.getMessage(), e);
        aTransaction.rollback();
        CompanyException aCompanyException = new CompanyException(e.getCause().getMessage(), e);
        throw aCompanyException;

    } finally {
        aSession.flush();
        aSession.close();
    }
    return motransiid;

}

From source file:org.openbravo.erpCommon.ad_forms.AcctServer.java

private BigDecimal calculateMultipleRatesDifferences(BigDecimal _amount, String currencyIDFrom,
        String currencyIDTo, DocLine line, ConnectionProvider conn) {
    // _amount * ((TrxRate *
    // AccountingRateCurrencyFromCurrencyTo)-AccountingRateCurrencyDocCurrencyTo)
    String conversionDate = DateAcct;
    String strDateFormat = OBPropertiesProvider.getInstance().getOpenbravoProperties()
            .getProperty("dateFormat.java");
    final SimpleDateFormat dateFormat = new SimpleDateFormat(strDateFormat);
    // Calculate accountingRateCurrencyFromCurrencyTo
    BigDecimal accountingRateCurrencyFromCurrencyTo = BigDecimal.ONE;
    if (!currencyIDFrom.equals(currencyIDTo)) {
        ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID,
                currencyIDFrom, currencyIDTo);
        if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                && line instanceof DocLine_FINReconciliation) {
            String transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
            FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class,
                    transactionID);/*from w w  w .  j a va2  s  . c o m*/
            conversionDate = dateFormat.format(transaction.getDateAcct());
            conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transaction.getId(),
                    currencyIDFrom, currencyIDTo);
        }
        if (conversionRateCurrentDoc != null) {
            accountingRateCurrencyFromCurrencyTo = conversionRateCurrentDoc.getRate();
        } else {
            // I try to find a reversal rate for the doc, if exists i apply it reversal as well
            if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                    && line instanceof DocLine_FINReconciliation) {
                String transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
                FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class,
                        transactionID);
                conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transaction.getId(),
                        currencyIDTo, currencyIDFrom);
            } else {
                conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID, currencyIDTo,
                        currencyIDFrom);
            }
            if (conversionRateCurrentDoc != null) {
                accountingRateCurrencyFromCurrencyTo = BigDecimal.ONE.divide(conversionRateCurrentDoc.getRate(),
                        MathContext.DECIMAL64);
            } else {
                accountingRateCurrencyFromCurrencyTo = getConvertionRate(currencyIDFrom, currencyIDTo,
                        conversionDate, "", AD_Client_ID, AD_Org_ID, conn);
            }
        }
    }

    // Calculate accountingRateCurrencyFromCurrencyTo
    BigDecimal accountingRateCurrencyDocCurrencyTo = BigDecimal.ONE;
    if (!C_Currency_ID.equals(currencyIDTo)) {
        ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID, C_Currency_ID,
                currencyIDTo);
        if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                && line instanceof DocLine_FINReconciliation) {
            String transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
            FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class,
                    transactionID);
            conversionDate = dateFormat.format(transaction.getTransactionDate());
            conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transaction.getId(),
                    C_Currency_ID, currencyIDTo);
        }
        if (conversionRateCurrentDoc != null) {
            accountingRateCurrencyDocCurrencyTo = conversionRateCurrentDoc.getRate();
        } else {
            // I try to find a reversal rate for the doc, if exists i apply it reversal as well
            if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                    && line instanceof DocLine_FINReconciliation) {
                String transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
                FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class,
                        transactionID);
                conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Transaction, transaction.getId(),
                        currencyIDTo, C_Currency_ID);
            } else {
                conversionRateCurrentDoc = getConversionRateDoc(AD_Table_ID, Record_ID, currencyIDTo,
                        C_Currency_ID);
            }
            if (conversionRateCurrentDoc != null) {
                accountingRateCurrencyDocCurrencyTo = BigDecimal.ONE.divide(conversionRateCurrentDoc.getRate(),
                        MathContext.DECIMAL64);
            } else {
                accountingRateCurrencyDocCurrencyTo = getConvertionRate(C_Currency_ID, currencyIDTo,
                        conversionDate, "", AD_Client_ID, AD_Org_ID, conn);
            }
        }
    }
    // Calculate transaction rate
    BigDecimal trxRate = BigDecimal.ONE;
    if (!C_Currency_ID.equals(currencyIDFrom)) {
        if (AD_Table_ID.equals(TABLEID_Payment)) {
            FIN_Payment payment = OBDal.getInstance().get(FIN_Payment.class, Record_ID);
            trxRate = payment.getFinancialTransactionConvertRate();
        } else if (AD_Table_ID.equals(TABLEID_Transaction) || AD_Table_ID.equals(TABLEID_Reconciliation)) {
            String transactionID = Record_ID;
            // When TableID = Reconciliation info is loaded from transaction
            if (AD_Table_ID.equals(AcctServer.TABLEID_Reconciliation)
                    && line instanceof DocLine_FINReconciliation) {
                transactionID = ((DocLine_FINReconciliation) line).getFinFinAccTransactionId();
            }
            FIN_FinaccTransaction transaction = OBDal.getInstance().get(FIN_FinaccTransaction.class,
                    transactionID);
            trxRate = transaction.getForeignConversionRate();
        }
    }
    Currency currencyFrom = OBDal.getInstance().get(Currency.class, currencyIDTo);
    return _amount
            .multiply(trxRate.multiply(accountingRateCurrencyDocCurrencyTo)
                    .subtract(accountingRateCurrencyFromCurrencyTo))
            .setScale(currencyFrom.getStandardPrecision().intValue(), BigDecimal.ROUND_HALF_EVEN);
}

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

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public BigDecimal getAusgegebeneMengePreis(Integer lossollmaterialIId, java.sql.Timestamp tStichtag,
        TheClientDto theClientDto) throws EJBExceptionLP {
    try {/*from www .ja va2 s  .  co  m*/
        BigDecimal bdMenge = new BigDecimal(0);
        BigDecimal bdWert = new BigDecimal(0);
        LosistmaterialDto[] losist = losistmaterialFindByLossollmaterialIId(lossollmaterialIId);
        for (int i = 0; i < losist.length; i++) {

            BigDecimal bdAusgegeben = getLagerFac().getMengeEinerBelegposition(LocaleFac.BELEGART_LOS,
                    losist[i].getIId(), tStichtag);

            if (Helper.short2boolean(losist[i].getBAbgang())) {

                BigDecimal bdPreis = getLagerFac().getGemittelterGestehungspreisEinerAbgangsposition(
                        LocaleFac.BELEGART_LOS, losist[i].getIId());
                bdMenge = bdMenge.add(bdAusgegeben);
                bdWert = bdWert.add(bdPreis.multiply(bdAusgegeben));
            } else {
                BigDecimal bdPreis = getLagerFac().getGemittelterEinstandspreisEinerZugangsposition(
                        LocaleFac.BELEGART_LOS, losist[i].getIId());
                bdMenge = bdMenge.subtract(bdAusgegeben);
                bdWert = bdWert.subtract(bdPreis.multiply(bdAusgegeben));
            }
        }
        if (bdMenge.doubleValue() == 0) {
            return bdMenge;
        } else {
            return bdWert.divide(bdMenge, BigDecimal.ROUND_HALF_EVEN);
        }
    } catch (RemoteException ex) {
        throwEJBExceptionLPRespectOld(ex);
        return null;
    }
}

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

public void aendereLosgroesse(Integer losIId, Integer neueLosgroesse,
        boolean bUeberzaehligesMaterialZurueckgeben, TheClientDto theClientDto) {
    LosDto losDto = losFindByPrimaryKey(losIId);
    if (losDto.getStatusCNr().equals(FertigungFac.STATUS_AUSGEGEBEN)
            || losDto.getStatusCNr().equals(FertigungFac.STATUS_IN_PRODUKTION)
            || losDto.getStatusCNr().equals(FertigungFac.STATUS_GESTOPPT)
            || losDto.getStatusCNr().equals(FertigungFac.STATUS_TEILERLEDIGT)) {

        if (!losDto.getNLosgroesse().equals(new BigDecimal(neueLosgroesse))) {

            BigDecimal bdErledigte = getErledigteMenge(losDto.getIId(), theClientDto);

            if (bdErledigte.doubleValue() > neueLosgroesse.doubleValue()) {
                throw new EJBExceptionLP(
                        EJBExceptionLP.FEHLER_FERTIGUNG_AENDERUNG_LOGROESSE_ZUVIELEABLIEFERUNGEN,
                        new Exception("bdErledigte.doubleValue()>neueLosgroesse.doubleValue()"));
            }/*  w  w w.  ja  va2s. c om*/

            Los los = em.find(Los.class, losDto.getIId());
            los.setNLosgroesse(new BigDecimal(neueLosgroesse));
            em.merge(los);
            em.flush();

            // Material
            LossollmaterialDto[] dtos = lossollmaterialFindByLosIId(losIId);
            for (int i = 0; i < dtos.length; i++) {
                LossollmaterialDto dto = dtos[i];
                // Sollmengen aendern
                BigDecimal sollsatzgroesse = dto.getNMenge().divide(losDto.getNLosgroesse(), 10,
                        BigDecimal.ROUND_HALF_EVEN);
                dto.setNMenge(
                        Helper.rundeKaufmaennisch(sollsatzgroesse.multiply(new BigDecimal(neueLosgroesse)), 3));
                updateLossollmaterial(dto, theClientDto);

                // Wenn kleiner je nach parameter
                // bUeberzaehligesMaterialZurueckgeben material
                // zurueckbuchen
                if (neueLosgroesse.doubleValue() < losDto.getNLosgroesse().doubleValue()
                        && bUeberzaehligesMaterialZurueckgeben == true) {
                    BigDecimal bdAusgegeben = getAusgegebeneMenge(dto.getIId(), null, theClientDto);
                    BigDecimal diff = bdAusgegeben.subtract(dto.getNMenge());
                    if (diff.doubleValue() > 0) {

                        LosistmaterialDto[] dtosLosist = losistmaterialFindByLossollmaterialIId(dto.getIId());

                        for (int j = 0; j < dtosLosist.length; j++) {
                            if (diff.doubleValue() > 0) {
                                BigDecimal istmenge = dtosLosist[j].getNMenge();

                                BigDecimal bdMengeNeu = null;

                                if (diff.doubleValue() > istmenge.doubleValue()) {
                                    bdMengeNeu = new BigDecimal(0);
                                    diff = diff.subtract(istmenge);
                                } else {
                                    bdMengeNeu = istmenge.subtract(diff);
                                    diff = new BigDecimal(0);
                                }

                                updateLosistmaterialMenge(dtosLosist[j].getIId(), bdMengeNeu, theClientDto);
                            }
                        }
                    }
                }

                // Fehlmengen aktualisieren
                try {
                    getFehlmengeFac().aktualisiereFehlmenge(LocaleFac.BELEGART_LOS, dto.getIId(), false,
                            theClientDto);
                } catch (RemoteException e) {
                    throwEJBExceptionLPRespectOld(e);
                }
            }

            // Arbeitsplan
            LossollarbeitsplanDto[] arbeitsplan = lossollarbeitsplanFindByLosIId(losIId);
            for (int i = 0; i < arbeitsplan.length; i++) {
                LossollarbeitsplanDto dto = arbeitsplan[i];
                // Gesamtzeit wird austomatisch aktualisiert
                updateLossollarbeitsplan(dto, theClientDto);

            }

        }

    } else {
        if (losDto.getStatusCNr().equals(FertigungFac.STATUS_STORNIERT)) {
            throw new EJBExceptionLP(EJBExceptionLP.FEHLER_FERTIGUNG_DAS_LOS_IST_STORNIERT,
                    new Exception("los " + losDto.getCNr() + " ist storniert"));
        } else if (losDto.getStatusCNr().equals(FertigungFac.STATUS_ERLEDIGT)) {
            throw new EJBExceptionLP(EJBExceptionLP.FEHLER_FERTIGUNG_DAS_LOS_IST_BEREITS_ERLEDIGT,
                    new Exception("los " + losDto.getCNr() + " ist bereits erledigt"));
        } else if (losDto.getStatusCNr().equals(FertigungFac.STATUS_ANGELEGT)) {
            throw new EJBExceptionLP(EJBExceptionLP.FEHLER_FERTIGUNG_DAS_LOS_IST_NOCH_NICHT_AUSGEGEBEN,
                    new Exception("los " + losDto.getCNr() + " ist noch nicht ausgegeben"));
        }
    }
}

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

private void aktualisiereAZAllerLosablieferungen(Integer losIId, TheClientDto theClientDto) {
    LosDto losDto = losFindByPrimaryKey(losIId);
    try {//from  www.  j  ava  2 s  .  c  o  m
        // Sollzeiten
        LossollarbeitsplanDto[] soll = lossollarbeitsplanFindByLosIId(losDto.getIId());
        int SOLL = 0;
        int IST = 1;
        int WERT = 2;
        // Sollzeiten nach Artikel verdichten
        HashMap<Integer, Object[]> listSollVerdichtet = new HashMap<Integer, Object[]>();
        for (int i = 0; i < soll.length; i++) {

            if (listSollVerdichtet.containsKey(soll[i].getArtikelIIdTaetigkeit())) {
                Object[] oTemp = listSollVerdichtet.get(soll[i].getArtikelIIdTaetigkeit());
                BigDecimal sollZeit = soll[i].getNGesamtzeit();
                if (soll[i].getMaschineIId() != null) {
                    sollZeit = sollZeit.multiply(new BigDecimal(2));
                }

                oTemp[SOLL] = ((BigDecimal) oTemp[SOLL]).add(sollZeit);

                oTemp[IST] = new BigDecimal(0.00);
                oTemp[WERT] = new BigDecimal(0.00);

                listSollVerdichtet.put(soll[i].getArtikelIIdTaetigkeit(), oTemp);
            } else {
                Object[] oZeile = new Object[3];
                BigDecimal sollZeit = soll[i].getNGesamtzeit();
                if (soll[i].getMaschineIId() != null) {
                    sollZeit = sollZeit.multiply(new BigDecimal(2));
                }
                oZeile[SOLL] = sollZeit;

                oZeile[IST] = new BigDecimal(0.00);
                oZeile[WERT] = new BigDecimal(0.00);

                listSollVerdichtet.put(soll[i].getArtikelIIdTaetigkeit(), oZeile);
            }
        }

        // Maschinenzeiten
        AuftragzeitenDto[] zeitenMaschine = getZeiterfassungFac().getAllMaschinenzeitenEinesBeleges(losIId,
                null, null, null, theClientDto);

        // "normale" Zeiten
        AuftragzeitenDto[] zeitenMann = getZeiterfassungFac().getAllZeitenEinesBeleges(LocaleFac.BELEGART_LOS,
                losIId, null, null, null, null, false, false, theClientDto);

        LosablieferungDto[] losablieferungDtos = losablieferungFindByLosIIdOhneNeuberechnungUndOhneSnrChnr(
                losIId, theClientDto);

        boolean bErledigtOderUeberliefert = false;
        BigDecimal bdGesamtAbgeliefert = new BigDecimal(0.00);
        for (int i = 0; i < losablieferungDtos.length; i++) {
            LosablieferungDto losablieferungDto = losablieferungDtos[i];
            bdGesamtAbgeliefert = bdGesamtAbgeliefert.add(losablieferungDto.getNMenge());
        }

        if (losDto.getStatusCNr().equals(LocaleFac.STATUS_ERLEDIGT)
                || bdGesamtAbgeliefert.doubleValue() >= losDto.getNLosgroesse().doubleValue()) {
            bErledigtOderUeberliefert = true;
        }

        BigDecimal bdKostenGesamt = new BigDecimal(0.00);
        BigDecimal bdVerbrauchteKostenGesamt = new BigDecimal(0.00);
        HashMap<Integer, BigDecimal> hmUeberigeZeitderVorhergehendenAblieferung = new HashMap();
        HashMap bdUeberigeKostenderVorhergehendenAblieferung = new HashMap<Object, BigDecimal>();

        for (int i = 0; i < losablieferungDtos.length; i++) {
            LosablieferungDto losablieferungDto = losablieferungDtos[i];

            HashMap<Integer, Object[]> hmAblieferung = new HashMap<Integer, Object[]>();
            Iterator<?> it = listSollVerdichtet.keySet().iterator();
            while (it.hasNext()) {
                Integer key = (Integer) it.next();
                Object[] oNew = new Object[3];
                Object[] oVorhanden = listSollVerdichtet.get(key);
                oNew[SOLL] = oVorhanden[SOLL];
                oNew[IST] = oVorhanden[IST];
                oNew[WERT] = oVorhanden[WERT];
                hmAblieferung.put(key, oNew);
            }

            for (int j = 0; j < zeitenMaschine.length; j++) {
                BigDecimal bdIst = new BigDecimal(0.00);

                if (zeitenMaschine[j].getTsEnde() != null) {
                    if (i == 0 && i == losablieferungDtos.length - 1) {
                        if (zeitenMaschine[j].getTsEnde().before(losablieferungDto.getTAendern())
                                || zeitenMaschine[j].getTsEnde().after(losablieferungDtos[0].getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMaschine[j].getDdDauer().doubleValue()));
                        }

                    } else if (i == 0) {
                        if (zeitenMaschine[j].getTsEnde().before(losablieferungDto.getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMaschine[j].getDdDauer().doubleValue()));

                        }
                    } else if (i == losablieferungDtos.length - 1) {
                        if (zeitenMaschine[j].getTsEnde().after(losablieferungDtos[i - 1].getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMaschine[j].getDdDauer().doubleValue()));
                        }
                    } else {
                        if (zeitenMaschine[j].getTsEnde().after(losablieferungDtos[i - 1].getTAendern())
                                && zeitenMaschine[j].getTsEnde().before(losablieferungDto.getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMaschine[j].getDdDauer().doubleValue()));
                        }
                    }
                }

                if (bdIst.doubleValue() > 0) {
                    bdKostenGesamt = bdKostenGesamt.add(zeitenMaschine[j].getBdKosten());
                    if (hmAblieferung.containsKey(zeitenMaschine[j].getArtikelIId())) {
                        Object[] oZeile = hmAblieferung.get(zeitenMaschine[j].getArtikelIId());
                        oZeile[IST] = ((BigDecimal) oZeile[IST]).add(bdIst);
                        oZeile[WERT] = ((BigDecimal) oZeile[WERT]).add(zeitenMaschine[j].getBdKosten());
                        hmAblieferung.put(zeitenMaschine[j].getArtikelIId(), oZeile);
                    } else {
                        Object[] oZeile = new Object[3];
                        oZeile[SOLL] = new BigDecimal(0.00);
                        oZeile[IST] = bdIst;
                        oZeile[WERT] = zeitenMaschine[j].getBdKosten();
                        hmAblieferung.put(zeitenMaschine[j].getArtikelIId(), oZeile);
                    }
                }

            }

            // Zeiten Mann
            for (int j = 0; j < zeitenMann.length; j++) {
                BigDecimal bdIst = new BigDecimal(0.00);

                if (zeitenMann[j].getTsEnde() != null) {
                    if (i == 0 && i == losablieferungDtos.length - 1) {
                        if (zeitenMann[j].getTsEnde().before(losablieferungDto.getTAendern())
                                || zeitenMann[j].getTsEnde().after(losablieferungDtos[0].getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMann[j].getDdDauer().doubleValue()));
                        }

                    }

                    else if (i == 0) {
                        if (zeitenMann[j].getTsEnde().before(losablieferungDto.getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMann[j].getDdDauer().doubleValue()));

                        }
                    } else if (i == losablieferungDtos.length - 1) {
                        if (zeitenMann[j].getTsEnde().after(losablieferungDtos[i - 1].getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMann[j].getDdDauer().doubleValue()));
                        }
                    } else {
                        if (zeitenMann[j].getTsEnde().after(losablieferungDtos[i - 1].getTAendern())
                                && zeitenMann[j].getTsEnde().before(losablieferungDto.getTAendern())) {
                            bdIst = bdIst.add(new BigDecimal(zeitenMann[j].getDdDauer().doubleValue()));
                        }
                    }
                }
                if (bdIst.doubleValue() > 0) {
                    bdKostenGesamt = bdKostenGesamt.add(zeitenMann[j].getBdKosten());
                    if (hmAblieferung.containsKey(zeitenMann[j].getArtikelIId())) {
                        Object[] oZeile = hmAblieferung.get(zeitenMann[j].getArtikelIId());
                        oZeile[IST] = ((BigDecimal) oZeile[IST]).add(bdIst);
                        oZeile[WERT] = ((BigDecimal) oZeile[WERT]).add(zeitenMann[j].getBdKosten());
                        hmAblieferung.put(zeitenMann[j].getArtikelIId(), oZeile);
                    } else {
                        Object[] oZeile = new Object[3];
                        oZeile[SOLL] = new BigDecimal(0.00);
                        oZeile[IST] = bdIst;
                        oZeile[WERT] = zeitenMann[j].getBdKosten();
                        hmAblieferung.put(zeitenMann[j].getArtikelIId(), oZeile);
                    }
                }
            }

            Iterator<?> itTemp = hmAblieferung.keySet().iterator();
            BigDecimal azWertDerAblieferung = new BigDecimal(0.00);
            while (itTemp.hasNext()) {
                Integer key = (Integer) itTemp.next();

                Object[] oZeile = hmAblieferung.get(key);

                // Sollsatzgroesze ermitteln
                BigDecimal bdIstAblieferung = (BigDecimal) oZeile[IST];

                // Vorherige uebrige Zeit dazuzaehlen
                if (hmUeberigeZeitderVorhergehendenAblieferung.containsKey(key)) {
                    bdIstAblieferung = bdIstAblieferung
                            .add((BigDecimal) hmUeberigeZeitderVorhergehendenAblieferung.get(key));
                }

                BigDecimal bdSollAblieferung = (BigDecimal) oZeile[SOLL];

                BigDecimal bdKostenAblieferung = (BigDecimal) oZeile[WERT];
                if (bdUeberigeKostenderVorhergehendenAblieferung.containsKey(key)) {
                    bdKostenAblieferung = bdKostenAblieferung
                            .add((BigDecimal) bdUeberigeKostenderVorhergehendenAblieferung.get(key));
                }

                if (bdSollAblieferung.doubleValue() != 0) {

                    // Sollsatzgroesse ermitteln

                    BigDecimal sollsatzgroesse = bdSollAblieferung
                            .divide(losDto.getNLosgroesse(), 4, BigDecimal.ROUND_HALF_EVEN)
                            .multiply(losablieferungDto.getNMenge());

                    BigDecimal maxSollsatzKosten = bdSollAblieferung.multiply(losablieferungDto.getNMenge());

                    BigDecimal tatsaechlicheKosten = null;
                    if (bdKostenAblieferung.doubleValue() > maxSollsatzKosten.doubleValue()) {
                        tatsaechlicheKosten = maxSollsatzKosten;

                    } else {
                        tatsaechlicheKosten = bdKostenAblieferung;
                    }

                    azWertDerAblieferung = azWertDerAblieferung.add(tatsaechlicheKosten);
                    if (bdKostenAblieferung.doubleValue() > azWertDerAblieferung.doubleValue()) {
                        bdUeberigeKostenderVorhergehendenAblieferung.put(key,
                                bdKostenAblieferung.subtract(azWertDerAblieferung));
                    }

                } else {
                    azWertDerAblieferung = azWertDerAblieferung.add(bdKostenAblieferung);
                }
                System.out.println(azWertDerAblieferung);
            }
            bdVerbrauchteKostenGesamt = bdVerbrauchteKostenGesamt.add(azWertDerAblieferung);

            // Wenn ERLEDIGT oder Ueberliefert //Den Rest hinzufuegen
            if (bErledigtOderUeberliefert && i == losablieferungDtos.length - 1) {
                BigDecimal restKosten = bdKostenGesamt.subtract(bdVerbrauchteKostenGesamt);
                azWertDerAblieferung = azWertDerAblieferung.add(restKosten);
            }
            if (losablieferungDto.getNMenge().doubleValue() != 0) {
                azWertDerAblieferung = azWertDerAblieferung.divide(losablieferungDto.getNMenge(), 4,
                        BigDecimal.ROUND_HALF_EVEN);
            }
            Losablieferung losablieferung = em.find(Losablieferung.class, losablieferungDto.getIId());
            if (losablieferung == null) {
                throw new EJBExceptionLP(EJBExceptionLP.FEHLER_BEI_FINDBYPRIMARYKEY, "");
            }
            losablieferung.setNArbeitszeitwert(azWertDerAblieferung);
            losablieferung.setNArbeitszeitwertdetailliert(azWertDerAblieferung);
        }

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

}