Example usage for java.math BigDecimal compareTo

List of usage examples for java.math BigDecimal compareTo

Introduction

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

Prototype

@Override
public int compareTo(BigDecimal val) 

Source Link

Document

Compares this BigDecimal with the specified BigDecimal .

Usage

From source file: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));
    }/*  w w w.j a va 2  s.c  om*/

    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:com.turborep.turbotracker.banking.service.BankingServiceImpl.java

@SuppressWarnings("unchecked")
@Override/* w w w .j  a  va  2s  . c  o m*/
public PrintCheckBean printCheck(Motransaction theMotransaction, Integer checkNumber, Integer yearID,
        Integer periodID, String userName, Integer userID) throws BankingException {
    PrintCheckBean aPrintBean = new PrintCheckBean();
    Session aSession = itsSessionFactory.openSession();
    Transaction aTransaction = null;
    String deletetemCheck = null, billArrayQuery = null, rxAddressIDQuery = null, vendorPayBeanQuery = null;
    StringBuffer totalAmountQuery = null;
    Molinkage aMolinkage = new Molinkage();
    Integer moLinkageId = null;
    Integer moTransactionId = null;
    Integer moLinkageDetailID = null;
    Integer[] rxMasterID = null;
    ArrayList<Integer> rxMasterID1 = new ArrayList<Integer>();
    ArrayList<BigDecimal> creditAmtUsed = new ArrayList<BigDecimal>();
    BigDecimal[] totalAmount = new BigDecimal[0];
    BigDecimal[] totalAmount1 = null;
    BigDecimal balAmount = new BigDecimal(0);
    BigDecimal balcalculationAmount = new BigDecimal(0);
    MoAccount aMoaccount = new MoAccount();
    checkDate = theMotransaction.getTransactionDate();
    int i = 0;
    int j = 0;
    try {
        aTransaction = aSession.beginTransaction();
        aTransaction.begin();

        deletetemCheck = "DELETE FROM moVendorCheckTemp";
        aSession.createSQLQuery(deletetemCheck).executeUpdate();

        billArrayQuery = "select veBillID from veBillPay where moAccountId=" + theMotransaction.getMoAccountId()
                + " and userID =" + userID;
        Query aQuery = aSession.createSQLQuery(billArrayQuery);
        List<?> billIds = aQuery.list();
        billId = new Integer[aQuery.list().size()];
        for (i = 0; i < billIds.size(); i++)
            billId[i] = (Integer) billIds.get(i);
        String rxMasterList = "SELECT BillPayUniqueIDs.rxMasterID FROM (SELECT rxMasterID FROM (SELECT veBill.rxMasterID FROM veBill LEFT JOIN veBillPay ON veBill.veBillID = veBillPay.veBillID WHERE veBillPay.ApplyingAmount<>0 and veBillPay.moAccountId="
                + theMotransaction.getMoAccountId() + " and veBillPay.userID = " + userID
                + ") AS BillPayIDs GROUP BY rxMasterID) AS BillPayUniqueIDs "
                + "INNER JOIN rxMaster ON BillPayUniqueIDs.rxMasterID = rxMaster.rxMasterID ORDER BY Name;";
        Query aQuery1 = aSession.createSQLQuery(rxMasterList);
        itsLogger.info(aQuery1.toString());
        List<?> rxMasterLists = aQuery1.list();
        rxMasterID = new Integer[aQuery1.list().size()];
        for (i = 0; i < rxMasterLists.size(); i++) {
            rxMasterID[i] = (Integer) rxMasterLists.get(i);
        }

        int counting = 0;
        totalAmount1 = new BigDecimal[rxMasterID.length];
        for (i = 0; i < rxMasterID.length; i++) {

            totalAmountQuery = new StringBuffer(
                    "SELECT SUM(P.ApplyingAmount) AS CheckAmount FROM veBillPay AS P INNER JOIN veBill AS B ON P.veBillID = B.veBillID Where P.moAccountId="
                            + theMotransaction.getMoAccountId() + " and P.userID = " + userID
                            + " and (B.rxMasterID =").append(rxMasterID[i]).append(")");
            Query aQuery2 = aSession.createSQLQuery(totalAmountQuery.toString());
            List<?> totalList = aQuery2.list();
            for (j = 0; j < totalList.size(); j++) {
                if ((BigDecimal) totalList.get(j) != null) {
                    BigDecimal amt = (BigDecimal) totalList.get(j);

                    if (amt.signum() < 0) {
                        rxMasterID1.add(rxMasterID[i]);
                        creditAmtUsed.add((BigDecimal) totalList.get(j));
                    } else {
                        totalAmount1[counting] = (BigDecimal) totalList.get(j);
                        counting++;
                    }
                }
            }
        }

        for (int t = 0; t < rxMasterID1.size(); t++) {
            rxMasterID = (Integer[]) ArrayUtils.removeElement(rxMasterID, rxMasterID1.get(t));
            itsLogger.info("rxMasterID::" + rxMasterID1.get(t));
        }

        if (rxMasterID.length > 0) {
            //Get rxAddress Information from normal payment
            rxAddressID = new Integer[rxMasterID.length];
            for (i = 0; i < rxMasterID.length; i++) {
                rxAddressIDQuery = "SELECT rxAddressID FROM rxAddress WHERE rxMasterID= " + rxMasterID[i]
                        + " and IsRemitTo = 1";
                Query aQuery3 = aSession.createSQLQuery(rxAddressIDQuery);
                List<?> rxAddressList = aQuery3.list();

                if (rxAddressList.size() > 0) {
                    rxAddressID[i] = (Integer) rxAddressList.get(0);
                } else {
                    rxAddressIDQuery = "SELECT rxAddressID FROM rxAddress WHERE rxMasterID= " + rxMasterID[i]
                            + " limit 1";
                    aQuery3 = aSession.createSQLQuery(rxAddressIDQuery);
                    rxAddressList = aQuery3.list();
                    rxAddressID[i] = (Integer) rxAddressList.get(0);
                }

            }
        } else {
            //Get rxAddress Information from credit payment
            rxAddressID = new Integer[rxMasterID1.size()];
            for (i = 0; i < rxMasterID1.size(); i++) {
                rxAddressIDQuery = "SELECT rxAddressID FROM rxAddress WHERE rxMasterID= " + rxMasterID1.get(i)
                        + " limit 1";
                Query aQuery3 = aSession.createSQLQuery(rxAddressIDQuery);
                itsLogger.info("Query2 " + aQuery3.toString());
                List<?> rxAddressList = aQuery3.list();
                for (j = 0; j < rxAddressList.size(); j++) {
                    if ((Integer) rxAddressList.get(j) != null)
                        rxAddressID[i] = (Integer) rxAddressList.get(j);
                }
            }
        }

        aMolinkage.setDummyVal(true);
        moLinkageId = (Integer) aSession.save(aMolinkage);
        int chkno = 0;
        chkno = checkNumber;
        if (counting != 0) // Normal Payment 
        {
            totalAmount = new BigDecimal[counting];
            for (int t = 0; t < counting; t++) {
                totalAmount[t] = totalAmount1[t];
            }
            for (i = 0; i < rxMasterID.length; i++) {

                List<VendorPayBean> payBeanlist = new ArrayList<VendorPayBean>();

                vendorPayBeanQuery = "SELECT veBillPay.veBillPayID, veBillPay.veBillID, veBillPay.ApplyingAmount, veBillPay.DiscountAmount,"
                        + "veBill.BillDate,veBill.InvoiceNumber,veBill.BillAmount,veBill.AppliedAmount,vePO.PONumber FROM veBill "
                        + "LEFT JOIN veBillPay ON veBill.veBillID = veBillPay.veBillID  LEFT JOIN vePO ON veBill.vePOID = vePO.vePOID "
                        + "WHERE veBillPay.ApplyingAmount<>0 AND veBillPay.moAccountId="
                        + theMotransaction.getMoAccountId() + " AND veBillPay.userID = " + userID
                        + " AND  veBill.rxMasterID= " + rxMasterID[i]
                        + " ORDER BY veBill.InvoiceNumber, veBill.BillDate";

                Query aQuery4 = aSession.createSQLQuery(vendorPayBeanQuery);
                payBeanlist = aQuery4.list();

                if (payBeanlist.size() <= 25) // pick invoice count less than 25 for particular vendor
                {
                    balAmount = new BigDecimal(0);
                    ArrayList<VendorPayBean> payBean = new ArrayList<VendorPayBean>();
                    balAmount = balAmount.add(totalAmount[i].negate());
                    Motransaction aMotransaction = new Motransaction();
                    aMotransaction.setRxMasterId(rxMasterID[i]);
                    aMotransaction.setRxAddressId(rxAddressID[i]);
                    aMotransaction.setCheckType(theMotransaction.getCheckType());
                    aMotransaction.setTransactionDate(theMotransaction.getTransactionDate());
                    aMotransaction.setMoAccountId(theMotransaction.getMoAccountId());
                    aMotransaction.setPrinted(theMotransaction.getPrinted());
                    aMotransaction.setAmount(totalAmount[i].negate());
                    balcalculationAmount = balcalculationAmount.add(balAmount); // for each Amount
                    aMotransaction.setBalance(theMotransaction.getBalance().add(balcalculationAmount));
                    aMotransaction.setCoAccountId(theMotransaction.getCoAccountId());
                    aMotransaction.setReference("" + chkno);
                    aMotransaction.setUniquechkRef("" + chkno);
                    aMotransaction.setMoTransactionTypeId(theMotransaction.getMoTransactionTypeId());

                    aMotransaction.setDescription("Vendor Write Checks");
                    aMotransaction.setVoid_((byte) 0);
                    aMotransaction.setReconciled((byte) 0);
                    aMotransaction.setDirectDeposit((byte) 0);
                    aMotransaction.setTempRec((byte) 0);
                    aMotransaction.setPageflagVoid(false);
                    moTransactionId = (Integer) aSession.save(aMotransaction);

                    Iterator<?> aIterator = aQuery4.list().iterator();
                    while (aIterator.hasNext()) {
                        Object[] aObj = (Object[]) aIterator.next();
                        VendorPayBean aPayBean = new VendorPayBean();
                        aPayBean.setVebillpayId((Integer) aObj[0]);
                        aPayBean.setVebillID((Integer) aObj[1]);
                        aPayBean.setApplyingAmount((BigDecimal) aObj[2]);
                        aPayBean.setDiscountAmount((BigDecimal) aObj[3]);
                        payBean.add(aPayBean);

                        WritecheckDetails wcObj = new WritecheckDetails();
                        wcObj.setWcDetailsID(1);
                        wcObj.setMoAccountID(theMotransaction.getMoAccountId());
                        wcObj.setMoTransactionId(moTransactionId);
                        wcObj.setMoTransactionDate(theMotransaction.getTransactionDate());
                        wcObj.setMoTransAmount(totalAmount[i].negate());
                        wcObj.setMoLinkappliedAmount((BigDecimal) aObj[2]);
                        wcObj.setMoLinkdiscount((BigDecimal) aObj[3]);
                        wcObj.setCheckno("" + chkno);
                        wcObj.setUserID(userID);
                        wcObj.setRxMasterID(rxMasterID[i]);
                        wcObj.setRxAddressID(rxAddressID[i]);
                        wcObj.setVeBillID((Integer) aObj[1]);
                        wcObj.setVeBillDate((Date) aObj[4]);
                        wcObj.setInvoiceNumber((String) aObj[5]);
                        wcObj.setVeBillAmount((BigDecimal) aObj[6]);
                        wcObj.setVeBillAppliedAmt((BigDecimal) aObj[7]);
                        wcObj.setPoNumber((String) aObj[8]);
                        wcObj.setVoidStatus(0);
                        wcObj.setVeBillBalance(((BigDecimal) aObj[6] != null ? (BigDecimal) aObj[6]
                                : BigDecimal.ZERO).subtract(
                                        ((BigDecimal) aObj[2] != null ? (BigDecimal) aObj[2] : BigDecimal.ZERO)
                                                .add((BigDecimal) aObj[3] != null ? (BigDecimal) aObj[3]
                                                        : BigDecimal.ZERO)));
                        aSession.save(wcObj);

                    }
                    /*String billtoRxmasterQuery = "SELECT vb.veBillID FROM veBillPay as vp INNER JOIN veBill as vb on vp.veBillID = vb.veBillID WHERE  vb.rxMasterID ="+rxMasterID[i]+";";
                    List<?> billList = aSession.createSQLQuery(billtoRxmasterQuery).list();*/
                    for (j = 0; j < payBean.size(); j++) {

                        Molinkagedetail aMolinkagedetail = new Molinkagedetail();
                        aMolinkagedetail.setVeBillId(payBean.get(j).getVebillID());
                        aMolinkagedetail.setAmount(payBean.get(j).getApplyingAmount());
                        aMolinkagedetail.setMoLinkageId(moLinkageId);
                        aMolinkagedetail.setDiscount(payBean.get(j).getDiscountAmount());
                        aMolinkagedetail.setMoTransactionId(moTransactionId);
                        moLinkageDetailID = (Integer) aSession.save(aMolinkagedetail);

                        Vebill aVebill = new Vebill();
                        aVebill = (Vebill) aSession.get(Vebill.class, payBean.get(j).getVebillID());
                        BigDecimal appliedAmount = aVebill.getAppliedAmount();
                        BigDecimal billAmount = aVebill.getBillAmount();
                        appliedAmount = appliedAmount.add(payBean.get(j).getApplyingAmount())
                                .add(payBean.get(j).getDiscountAmount());
                        aVebill.setAppliedAmount(appliedAmount);
                        aVebill.setCreditUsed("0");

                        if (appliedAmount.compareTo(billAmount) == 0)
                            aVebill.setTransactionStatus(2);
                        else
                            aVebill.setTransactionStatus(1);

                        aSession.update(aVebill);

                        /**Created by: Leo  ID:110 
                         * Date:04/07/2015
                         * Purpose: To store payment history */

                        if (payBean.get(j).getApplyingAmount().signum() > 0) {
                            VeBillPaymentHistory aVeBillPaymentHistory = new VeBillPaymentHistory();
                            aVeBillPaymentHistory.setVeBillID(payBean.get(j).getVebillID());
                            aVeBillPaymentHistory.setCheckNo("" + chkno);
                            aVeBillPaymentHistory.setDatePaid(theMotransaction.getTransactionDate());
                            aVeBillPaymentHistory.setAmountVal(payBean.get(j).getApplyingAmount());
                            aSession.save(aVeBillPaymentHistory);
                        }

                        //added by prasant 
                        if (payBean.get(j).getApplyingAmount().signum() < 0) {

                            System.out.println(
                                    "=======================================================================================================");
                            System.out.println(
                                    "Normal  Payment To store payment history when amount is credit chk:"
                                            + chkno + "Amount" + payBean.get(j).getApplyingAmount());
                            System.out.println(
                                    "=======================================================================================================");

                            VeBillPaymentHistory aVeBillPaymentHistory = new VeBillPaymentHistory();
                            aVeBillPaymentHistory.setVeBillID(payBean.get(j).getVebillID());
                            aVeBillPaymentHistory.setCheckNo("" + chkno);
                            aVeBillPaymentHistory.setDatePaid(theMotransaction.getTransactionDate());
                            aVeBillPaymentHistory.setAmountVal(payBean.get(j).getApplyingAmount());
                            aSession.save(aVeBillPaymentHistory);
                        }

                        //end

                    }
                    Movendorchecktemp amoVendorCheckTemp = new Movendorchecktemp();
                    amoVendorCheckTemp.setMoTransactionId(moTransactionId);
                    aSession.save(amoVendorCheckTemp);
                    chkno++;

                } else {
                    int veBilllistCount = payBeanlist.size() / 25; // "segment spliting" for pdf and generate new check no for each page

                    if ((payBeanlist.size() % 25) > 0) // add 1 segment if remainder comes
                        veBilllistCount += 1;

                    int valSublist = 0;
                    for (int cb = 1; cb <= veBilllistCount; cb++) {
                        valSublist = (cb - 1) * 25; // calculation part for picking data from arralist.
                        balAmount = new BigDecimal(0);
                        ArrayList<VendorPayBean> payBean = new ArrayList<VendorPayBean>();
                        balAmount = balAmount.add(totalAmount[i].negate());
                        Motransaction aMotransaction = new Motransaction();
                        aMotransaction.setRxMasterId(rxMasterID[i]);
                        aMotransaction.setRxAddressId(rxAddressID[i]);
                        aMotransaction.setTransactionDate(theMotransaction.getTransactionDate());
                        aMotransaction.setMoAccountId(theMotransaction.getMoAccountId());
                        aMotransaction.setPrinted(theMotransaction.getPrinted());
                        aMotransaction.setCoAccountId(theMotransaction.getCoAccountId());
                        aMotransaction.setReference("" + chkno);
                        aMotransaction.setMoTransactionTypeId(theMotransaction.getMoTransactionTypeId());

                        if (cb == 1) {
                            aMotransaction.setUniquechkRef("" + chkno);
                            aMotransaction.setDescription("Vendor Write Checks");
                            aMotransaction.setCheckType(theMotransaction.getCheckType());
                            aMotransaction.setAmount(totalAmount[i].negate());
                            balcalculationAmount = balcalculationAmount.add(balAmount); // for each Amount
                            aMotransaction.setBalance(theMotransaction.getBalance().add(balcalculationAmount));
                            aMotransaction.setVoid_((byte) 0);
                            aMotransaction.setPageflagVoid(false);
                        } else {
                            aMotransaction.setUniquechkRef("" + (chkno - (cb - 1)));
                            aMotransaction.setDescription("***VOID***");
                            aMotransaction.setStatus(true);
                            aMotransaction.setAmount(BigDecimal.ZERO);
                            aMotransaction.setVoid_((byte) 0);
                            aMotransaction.setPageflagVoid(true);
                            balcalculationAmount = balcalculationAmount.add(BigDecimal.ZERO); // for each Amount
                            aMotransaction.setBalance(theMotransaction.getBalance().add(balcalculationAmount));
                        }

                        aMotransaction.setReconciled((byte) 0);
                        aMotransaction.setDirectDeposit((byte) 0);
                        aMotransaction.setTempRec((byte) 0);
                        moTransactionId = (Integer) aSession.save(aMotransaction);

                        Iterator<?> aIterator = null;

                        if (cb * 25 < payBeanlist.size()) // pick data from list using index
                            aIterator = aQuery4.list().subList(valSublist, cb * 25).iterator();
                        else
                            aIterator = aQuery4.list().subList(valSublist, payBeanlist.size()).iterator();

                        while (aIterator.hasNext()) {
                            Object[] aObj = (Object[]) aIterator.next();
                            VendorPayBean aPayBean = new VendorPayBean();
                            aPayBean.setVebillpayId((Integer) aObj[0]);
                            aPayBean.setVebillID((Integer) aObj[1]);
                            aPayBean.setApplyingAmount((BigDecimal) aObj[2]);
                            aPayBean.setDiscountAmount((BigDecimal) aObj[3]);
                            payBean.add(aPayBean);

                            WritecheckDetails wcObj = new WritecheckDetails();
                            wcObj.setWcDetailsID(1);
                            wcObj.setMoAccountID(theMotransaction.getMoAccountId());
                            wcObj.setMoTransactionId(moTransactionId);
                            wcObj.setMoTransactionDate(theMotransaction.getTransactionDate());
                            wcObj.setMoTransAmount(totalAmount[i].negate());
                            wcObj.setMoLinkappliedAmount((BigDecimal) aObj[2]);
                            wcObj.setMoLinkdiscount((BigDecimal) aObj[3]);
                            wcObj.setCheckno("" + chkno);
                            wcObj.setUserID(userID);
                            wcObj.setRxMasterID(rxMasterID[i]);
                            wcObj.setRxAddressID(rxAddressID[i]);
                            wcObj.setVeBillID((Integer) aObj[1]);
                            wcObj.setVeBillDate((Date) aObj[4]);
                            wcObj.setInvoiceNumber((String) aObj[5]);
                            wcObj.setVeBillAmount((BigDecimal) aObj[6]);
                            wcObj.setVeBillAppliedAmt((BigDecimal) aObj[7]);
                            wcObj.setPoNumber((String) aObj[8]);
                            wcObj.setVeBillBalance(
                                    ((BigDecimal) aObj[6] != null ? (BigDecimal) aObj[6] : BigDecimal.ZERO)
                                            .subtract(((BigDecimal) aObj[2] != null ? (BigDecimal) aObj[2]
                                                    : BigDecimal.ZERO).add(
                                                            (BigDecimal) aObj[3] != null ? (BigDecimal) aObj[3]
                                                                    : BigDecimal.ZERO)));
                            if (valSublist > 0)
                                wcObj.setVoidStatus(1);
                            else
                                wcObj.setVoidStatus(0);
                            aSession.save(wcObj);

                        }
                        /*String billtoRxmasterQuery = "SELECT vb.veBillID FROM veBillPay as vp INNER JOIN veBill as vb on vp.veBillID = vb.veBillID WHERE  vb.rxMasterID ="+rxMasterID[i]+";";
                        List<?> billList = aSession.createSQLQuery(billtoRxmasterQuery).list();*/
                        for (j = 0; j < payBean.size(); j++) {

                            Molinkagedetail aMolinkagedetail = new Molinkagedetail();
                            aMolinkagedetail.setVeBillId(payBean.get(j).getVebillID());
                            aMolinkagedetail.setAmount(payBean.get(j).getApplyingAmount());
                            aMolinkagedetail.setMoLinkageId(moLinkageId);
                            aMolinkagedetail.setDiscount(payBean.get(j).getDiscountAmount());
                            aMolinkagedetail.setMoTransactionId(moTransactionId);
                            moLinkageDetailID = (Integer) aSession.save(aMolinkagedetail);

                            Vebill aVebill = new Vebill();
                            aVebill = (Vebill) aSession.get(Vebill.class, payBean.get(j).getVebillID());
                            BigDecimal appliedAmount = aVebill.getAppliedAmount();
                            BigDecimal billAmount = aVebill.getBillAmount();
                            appliedAmount = appliedAmount.add(payBean.get(j).getApplyingAmount())
                                    .add(payBean.get(j).getDiscountAmount());
                            aVebill.setAppliedAmount(appliedAmount);
                            aVebill.setCreditUsed("0");

                            if (appliedAmount.compareTo(billAmount) == 0)
                                aVebill.setTransactionStatus(2);
                            else
                                aVebill.setTransactionStatus(1);

                            aSession.update(aVebill);

                            /**Created by: Leo  ID:110 
                             * Date:04/07/2015
                             * Purpose: To store payment history */

                            if (payBean.get(j).getApplyingAmount().signum() > 0) {
                                VeBillPaymentHistory aVeBillPaymentHistory = new VeBillPaymentHistory();
                                aVeBillPaymentHistory.setVeBillID(payBean.get(j).getVebillID());
                                aVeBillPaymentHistory.setCheckNo("" + chkno);
                                aVeBillPaymentHistory.setDatePaid(theMotransaction.getTransactionDate());
                                aVeBillPaymentHistory.setAmountVal(payBean.get(j).getApplyingAmount());
                                aSession.save(aVeBillPaymentHistory);
                            }
                        }
                        Movendorchecktemp amoVendorCheckTemp = new Movendorchecktemp();
                        amoVendorCheckTemp.setMoTransactionId(moTransactionId);
                        aSession.save(amoVendorCheckTemp);
                        chkno++;
                    }

                }
            }
            /**Inserting GlTransaction*/
            payingVendorBillDiscount1(theMotransaction.getMoAccountId(), checkNumber, yearID, periodID,
                    userName, theMotransaction.getTransactionDate(), userID);

            /** Delete VeBillPay **/
            String rxMasterIds = StringUtils.join(rxMasterID, ',');
            if (rxMasterID.length > 0) {
                vendorPayBeanQuery = "DELETE FROM veBillPay WHERE veBillPayID IN (SELECT * FROM (SELECT vP.veBillPayID FROM veBillPay vP,veBill v WHERE vP.moAccountId="
                        + theMotransaction.getMoAccountId() + " AND vP.userID = " + userID
                        + "  AND vP.veBillID = v.veBillID AND v.rxMasterID IN (" + rxMasterIds
                        + ")) AS subQuery)";
                aSession.createSQLQuery(vendorPayBeanQuery).executeUpdate();
            }
            BigDecimal totalamount = new BigDecimal(0);
            for (i = 0; i < totalAmount.length; i++) {
                if (totalAmount[i] != null)
                    totalamount = totalamount.add(totalAmount[i]);
            }

            aMoaccount = (MoAccount) aSession.get(MoAccount.class, theMotransaction.getMoAccountId());
            aMoaccount.setNextCheckNumber(chkno);

            //BigDecimal openBalance = aMoaccount.getOpenBalance();
            /*openBalance = openBalance.subtract(totalamount);
            aMoaccount.setOpenBalance(openBalance);*/
            BigDecimal substractions = aMoaccount.getSubtractions();
            substractions = substractions.add(totalamount);
            aMoaccount.setSubtractions(substractions);
            aSession.update(aMoaccount);
            aTransaction.commit();

        } else // Credit Payment 
        {
            /**Created by: Leo  ID:110 
             * Date:04/06/2015
             * Purpose: for credit payments */

            String creditVeBillID = "";

            for (i = 0; i < rxMasterID1.size(); i++) { // iterate credit rxMasterIDs
                balAmount = new BigDecimal(0);
                ArrayList<VendorPayBean> payBean = new ArrayList<VendorPayBean>();
                BigDecimal pickNegativeAmt = new BigDecimal(0);

                vendorPayBeanQuery = "SELECT veBillPay.veBillPayID, veBillPay.veBillID, veBillPay.ApplyingAmount, veBillPay.DiscountAmount "
                        + "FROM veBill LEFT JOIN veBillPay ON veBill.veBillID = veBillPay.veBillID "
                        + "WHERE veBillPay.ApplyingAmount<>0 AND veBillPay.moAccountId="
                        + theMotransaction.getMoAccountId() + " and veBillPay.userID = " + userID
                        + " And  veBill.rxMasterID= " + rxMasterID1.get(i)
                        + " ORDER BY veBill.InvoiceNumber, veBill.BillDate;";
                Query aQuery4 = aSession.createSQLQuery(vendorPayBeanQuery); // get All veBillPay Details
                Iterator<?> aIterator = aQuery4.list().iterator();
                while (aIterator.hasNext()) {
                    Object[] aObj = (Object[]) aIterator.next();
                    VendorPayBean aPayBean = new VendorPayBean();
                    aPayBean.setVebillpayId((Integer) aObj[0]);
                    aPayBean.setVebillID((Integer) aObj[1]);
                    aPayBean.setApplyingAmount((BigDecimal) aObj[2]);
                    aPayBean.setDiscountAmount((BigDecimal) aObj[3]);
                    if (aPayBean.getApplyingAmount().signum() < 0) {
                        pickNegativeAmt = pickNegativeAmt.add(aPayBean.getApplyingAmount()); //sum of negative Amount only
                        if (creditVeBillID.equals("")) // Get All veBill IDs
                            creditVeBillID = "" + (Integer) aObj[1];
                        else
                            creditVeBillID = creditVeBillID + "," + (Integer) aObj[1];
                    }
                    payBean.add(aPayBean);
                }

                balAmount = balAmount.add(pickNegativeAmt.negate().add(creditAmtUsed.get(i))); // sum of all applying amt without credit Amount

                for (j = 0; j < payBean.size(); j++) { // Iterate veBill IDs

                    Vebill aVebill = new Vebill();
                    aVebill = (Vebill) aSession.get(Vebill.class, payBean.get(j).getVebillID());
                    BigDecimal appliedAmount = aVebill.getAppliedAmount();
                    BigDecimal billAmount = aVebill.getBillAmount();
                    itsLogger.info(payBean.get(j).getApplyingAmount());
                    /**
                     * Note: Credit bill don't update check no. credit used bills only need check no.
                     */

                    if (payBean.get(j).getApplyingAmount().signum() < 0) // check whether Applying Amt is in negative value
                    {

                        if (payBean.get(j).getApplyingAmount().negate().compareTo(balAmount) == 1) // check credit amount is greater or not
                        {
                            appliedAmount = appliedAmount.add(balAmount.negate())
                                    .add(payBean.get(j).getDiscountAmount());
                            aVebill.setAppliedAmount(appliedAmount);
                        } else {
                            appliedAmount = appliedAmount.add(payBean.get(j).getApplyingAmount())
                                    .add(payBean.get(j).getDiscountAmount());
                            aVebill.setAppliedAmount(appliedAmount);
                            balAmount = balAmount.add(payBean.get(j).getApplyingAmount());
                        }
                        aVebill.setCreditUsed("0");
                        itsLogger.info(balAmount);
                    } else {
                        /**Created by: Leo  ID:110 
                         * Date:04/07/2015
                         * Purpose: To store payment history */

                        appliedAmount = appliedAmount.add(payBean.get(j).getApplyingAmount())
                                .add(payBean.get(j).getDiscountAmount());

                        VeBillPaymentHistory aVeBillPaymentHistory = new VeBillPaymentHistory();
                        aVeBillPaymentHistory.setVeBillID(payBean.get(j).getVebillID());
                        aVeBillPaymentHistory.setCheckNo("" + chkno);
                        aVeBillPaymentHistory.setDatePaid(theMotransaction.getTransactionDate());
                        aVeBillPaymentHistory.setAmountVal(appliedAmount);
                        aSession.save(aVeBillPaymentHistory);

                        aVebill.setAppliedAmount(appliedAmount);
                        if (aVebill.getCreditUsed() != null && !aVebill.getCreditUsed().equals("0"))
                            aVebill.setCreditUsed(aVebill.getCreditUsed() + "," + creditVeBillID);
                        else
                            aVebill.setCreditUsed("" + creditVeBillID);

                        itsLogger.info(appliedAmount);
                    }

                    if (appliedAmount.compareTo(billAmount) == 0)
                        aVebill.setTransactionStatus(2);
                    else
                        aVebill.setTransactionStatus(1);
                    aSession.update(aVebill);
                }
                Movendorchecktemp amoVendorCheckTemp = new Movendorchecktemp();
                amoVendorCheckTemp.setMoTransactionId(moTransactionId);
                aSession.save(amoVendorCheckTemp);
                chkno++;
            }

            aMoaccount = (MoAccount) aSession.get(MoAccount.class, theMotransaction.getMoAccountId());
            aMoaccount.setNextCheckNumber(chkno);
            aSession.update(aMoaccount);

            aTransaction.commit();
        }

        if (rxMasterID.length > 0) {
            aPrintBean.setReference("Success");
        } else {
            aPrintBean.setReference("Error");
        }

    } catch (Exception e) {
        itsLogger.error(e.getMessage(), e);

        aTransaction.rollback();

        if (rxMasterID.length > 0) {
            aPrintBean.setReference("Success");
        } else {
            aPrintBean.setReference("Error");
        }

        BankingException aBankingException = new BankingException(e.getMessage(), e);
        throw aBankingException;
    } finally {
        aSession.flush();
        aSession.close();
        deletetemCheck = null;
        billArrayQuery = null;
        rxAddressIDQuery = null;
        vendorPayBeanQuery = null;
        totalAmountQuery = null;
    }
    return aPrintBean;
}

From source file:com.ugam.collage.plus.service.people_count.impl.PeopleAccountingServiceImpl.java

/**
 * @param empcntClientProjectDataList//w  w w.ja v a  2 s.c o  m
 * @param empClientProjectTeamStructList
 * @param employee
 * @param month
 * @param year
 * @param costCentre
 * @param countType
 * @param allignedTimeZero
 * @param assistedTimeZero
 * @param apportionedTimeZero
 * @param allignedTimeOne
 * @param totalTimeOne
 */
private void getSingleProjectDetail(List<EmpcntClientProjectData> empOpenCntClientProjectDataList,
        List<EmpcntClientProjectData> empCloseCntClientProjectDataList,
        List<EmpClientProjectTeamStruct> empClientProjectTeamStructList, EmployeeMaster employee,
        TabMonth month, TabYear year, CostCentre costCentre, CountClassification countType,
        BigDecimal allignedTimeZero, BigDecimal assistedTimeZero, BigDecimal apportionedTimeZero,
        BigDecimal allignedTimeOne, BigDecimal totalTimeOne, Integer countTypeId,
        Map<String, EmployeePcTagsTeamStruct> employeePcTagsTeamStructMap) {

    /*
     * Also assign to assisted if project detail present in both assigned
     * and unassigned list
     * 
     * Note : Only in unassigned project . do the remaining count as per
     * revenue to apportion
     * 
     * If not present in revenue table then go to zero project details
     */
    logger.debug("<====getSingleProjectDetail START====>");
    Integer employeeId = employee.getEmployeeId();
    Integer yearId = year.getYearId();
    Integer monthId = month.getMonthId();
    String costCentreId = costCentre.getCostCentreId();
    BigDecimal deviderHour = new BigDecimal(Constants.TOTAL_WORKING_HOURS);
    logger.debug("getSingleProjectDetail parameter===>" + employeeId + "::" + yearId + "::" + monthId + "::"
            + costCentreId + "::" + deviderHour);

    // Get project details
    Map<Integer, EmpClientProjectTeamStruct> employeeProjectIds = new HashMap<Integer, EmpClientProjectTeamStruct>();

    Map<Integer, EmpClientProjectTeamStruct> validEmployeeProjectIds = new HashMap<Integer, EmpClientProjectTeamStruct>();

    for (EmpClientProjectTeamStruct empClientProjectTeamStructThree : empClientProjectTeamStructList) {
        employeeProjectIds.put(empClientProjectTeamStructThree.getProjectMaster().getProjectId(),
                empClientProjectTeamStructThree);
    }

    validEmployeeProjectIds.putAll(employeeProjectIds);
    // logger.debug("validEmployeeProjectIds 1:size===>" +
    // validEmployeeProjectIds.size());

    // check in revenue table
    for (Integer key : employeeProjectIds.keySet()) {
        EmpClientProjectTeamStruct mapValues = employeeProjectIds.get(key);
        List<CollageProjectRevenue> listValues = collageProjectRevenueDao
                .findByYearIdMonthIdProjectIdCostCentreId(mapValues.getTabYear().getYearId(),
                        mapValues.getTabMonth().getMonthId(), mapValues.getProjectMaster().getProjectId(),
                        costCentre.getCostCentreId());
        if (listValues.isEmpty()) {
            validEmployeeProjectIds.remove(key);
        }
    }
    // logger.debug("validEmployeeProjectIds 2:size===>" +
    // validEmployeeProjectIds.size());
    if (validEmployeeProjectIds.isEmpty()) {
        getZeroProjectsDetail(yearId, monthId, costCentreId, empOpenCntClientProjectDataList,
                empCloseCntClientProjectDataList, employee, month, year, costCentre, countType,
                allignedTimeZero, assistedTimeZero, totalTimeOne, totalTimeOne, countTypeId,
                employeePcTagsTeamStructMap);
    }
    // Get list of project from execution data for that employee
    List<Integer> projectIdList = executionDataDao.findByPersonYearMonthCostCentre(employeeId, yearId, monthId,
            costCentreId);
    // logger.debug("execution data projects===>" + projectIdList.size());

    if (projectIdList.isEmpty()) {
        // logger.debug("Contain InValid projects :(Assign count one)===>");

        for (Integer projectId : validEmployeeProjectIds.keySet()) {
            EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
            // logger.debug("978: Contain InValid projects :(Assign count one)===>"+1);
            EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                    mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                    costCentre, allignedTimeOne, assistedTimeZero, apportionedTimeZero, allignedTimeOne);
            if (countTypeId == 1) {
                empOpenCntClientProjectDataList.add(empcntClientProjectData);
            } else if (countTypeId == 2) {
                empCloseCntClientProjectDataList.add(empcntClientProjectData);
            }
        }
    } else {
        // logger.debug("Else Contain Valid projects===>");
        Integer validEmployeeProjectCount = validEmployeeProjectIds.size();
        // Get valid projects list=>project is both revenue data and
        // execution data
        Set<Integer> validAllProjects = new HashSet<Integer>();
        for (Integer projectId : projectIdList) {
            List<CollageProjectRevenue> listValues = collageProjectRevenueDao
                    .findByYearIdMonthIdProjectIdCostCentreId(yearId, monthId, projectId, costCentreId);
            if (!listValues.isEmpty()) {
                validAllProjects.add(projectId);
            }

        }
        Integer validAllProjectCount = validAllProjects.size();
        // logger.debug("validAllProjects :size===>" +
        // validAllProjects.size());
        // Total hour worked by an Employee
        List<BigDecimal> toatalHours = executionDataDao.findByPersonIdYearIdMonthIdCostCentreId(employeeId,
                yearId, monthId, costCentreId);
        BigDecimal toatlTime = toatalHours.get(0);
        // logger.debug("ToatalHours===>" + toatlTime);

        // Separate assigned projects from execution data projects
        Map<Integer, BigDecimal> assignedProjects = new HashMap<Integer, BigDecimal>();
        Map<Integer, BigDecimal> unAssignedProjects = new HashMap<Integer, BigDecimal>();
        List<Object[]> allProjectTimeList = executionDataDao
                .findByEmployeeIdYearIdMonthIdCostCentreId(employeeId, yearId, monthId, costCentreId);
        for (Object[] result : allProjectTimeList) {
            Integer projectId = (Integer) result[0];
            BigDecimal hour = (BigDecimal) result[1];
            Integer companyId = (Integer) result[2];
            if (validEmployeeProjectIds.containsKey(projectId) && validAllProjects.contains(projectId)) {
                // logger.debug("UnAssignedProjects===>" +
                // projectId+"::"+hour+"::"+companyId);
                assignedProjects.put(projectId, hour);
            }
            if (!validEmployeeProjectIds.containsKey(projectId) && validAllProjects.contains(projectId)) {
                // logger.debug("assignedProjects===>" +
                // projectId+"::"+hour+"::"+companyId);
                unAssignedProjects.put(projectId, hour);
            }
        }
        if (validEmployeeProjectCount == 1 && validAllProjectCount == 1
                && validAllProjects.containsAll(validEmployeeProjectIds.keySet())
                && unAssignedProjects.isEmpty()) {

            // logger.debug("validEmployeeProjectCount==validAllProjectCount :(Only in assigned projects)");
            for (Integer key : assignedProjects.keySet()) {
                // Get time spent on each project by employee id
                Integer projectId = key;
                EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                // logger.debug("1034 :validEmployeeProjectCount==validAllProjectCount :(Only in assigned projects)===>1");
                EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                        mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                        costCentre, allignedTimeOne, assistedTimeZero, apportionedTimeZero, allignedTimeOne);
                if (countTypeId == 1) {
                    empOpenCntClientProjectDataList.add(empcntClientProjectData);
                }
                if (countTypeId == 2) {
                    empCloseCntClientProjectDataList.add(empcntClientProjectData);
                }
            }

        } else if (!assignedProjects.isEmpty() && !unAssignedProjects.isEmpty()) {
            // logger.debug("1047 : Both in assigned and unassigned projects===>");
            if (toatlTime.compareTo(new BigDecimal(Constants.TOTAL_WORKING_HOURS)) >= 0) {
                // logger.debug("Worked hours===> >=168");
                for (Integer key : assignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = assignedProjects.get(key);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("1056 :assigned:(Both in assigned and unassigned projects===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, workedHours, assistedTimeZero, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("1073 :unassigned :(Both in assigned and unassigned projects===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            } else {
                // logger.debug("Worked hours===> <168");
                BigDecimal totalUnAssingnedHours = BigDecimal.ZERO;
                BigDecimal assingnedHours = BigDecimal.ZERO;
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    BigDecimal workedHours = timeByProject.divide(deviderHour, 2, RoundingMode.HALF_EVEN);
                    totalUnAssingnedHours = totalUnAssingnedHours.add(workedHours);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // Assign to assisted count for unAssignedProjects
                    Integer projectId = key;
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    // logger.debug("769: Assisted hours (Both in assigned and unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                totalUnAssingnedHours = BigDecimal.ONE.subtract(totalUnAssingnedHours);
                // logger.debug("totalUnAssingnedHours===> "+totalUnAssingnedHours);
                for (Map.Entry<Integer, BigDecimal> entry : assignedProjects.entrySet()) {
                    assingnedHours = assingnedHours.add(entry.getValue());
                }

                // logger.debug("assingnedHours===> "+assingnedHours);
                for (Integer key : assignedProjects.keySet()) {
                    Integer projectId = key;
                    BigDecimal timeByProject = assignedProjects.get(key);
                    // logger.debug("1119 :projectId : timeByProject===> "+projectId+" : "+timeByProject);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal averageWorkedHours = timeByProject.divide(assingnedHours, 2,
                            RoundingMode.HALF_EVEN);
                    // logger.debug("1121 :assingnedHours : totalUnAssingnedHours===> "+assingnedHours+" : "+totalUnAssingnedHours);
                    BigDecimal actualWorkedHours = averageWorkedHours.multiply(totalUnAssingnedHours);
                    actualWorkedHours = actualWorkedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("1124 :averageWorkedHours : actualWorkedHours===> "+averageWorkedHours+" : "+actualWorkedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, actualWorkedHours, assistedTimeZero, apportionedTimeZero,
                            actualWorkedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            }
        }

        else if (assignedProjects.isEmpty() && !unAssignedProjects.isEmpty()) {
            // logger.debug("In  unassigned projects only===>");
            if (toatlTime.compareTo(new BigDecimal(Constants.TOTAL_WORKING_HOURS)) >= 0) {
                // logger.debug("Worked hours===> >=168");
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("1148 :In unassigned projects only===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            } else {
                // logger.debug("Worked hours===> <168");
                BigDecimal totalUnAssingnedHours = BigDecimal.ZERO;
                BigDecimal assingnedHours = BigDecimal.ZERO;
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    BigDecimal workedHours = timeByProject.divide(deviderHour, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    totalUnAssingnedHours = totalUnAssingnedHours.add(workedHours);

                    // Assign to assisted count for unAssignedProjects
                    Integer projectId = key;
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    // logger.debug("1173: Assisted hours (In unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                logger.debug("1209 totalUnAssingnedHours===> " + totalUnAssingnedHours);

                BigDecimal remainProportion = BigDecimal.ONE.subtract(totalUnAssingnedHours);
                logger.debug("remainProportion===> " + remainProportion);
                getRevenueCountProportion(empOpenCntClientProjectDataList, empCloseCntClientProjectDataList,
                        employee, month, year, costCentre, countType, remainProportion, unAssignedProjects,
                        countTypeId, employeePcTagsTeamStructMap);

            }
        }

    }
    // logger.debug("<====getSingleProjectDetail END====>");
}

From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java

private ChangedTransactionDetail handleRefundTransaction(final LoanTransaction loanTransaction,
        final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) {

    ChangedTransactionDetail changedTransactionDetail = null;

    final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND,
            LoanStatus.fromInt(this.loanStatus));
    this.loanStatus = statusEnum.getValue();

    loanTransaction.updateLoan(this);

    // final boolean isTransactionChronologicallyLatest =
    // isChronologicallyLatestRefund(loanTransaction,
    // this.loanTransactions);

    if (status().isOverpaid() || status().isClosed()) {

        final String errorMessage = "This refund option is only for active loans ";
        throw new InvalidLoanStateTransitionException("transaction", "is.exceeding.overpaid.amount",
                errorMessage, this.totalOverpaid, loanTransaction.getAmount(getCurrency()).getAmount());

    } else if (this.getTotalPaidInRepayments().isZero()) {
        final String errorMessage = "Cannot refund when no payment has been made";
        throw new InvalidLoanStateTransitionException("transaction", "no.payment.yet.made.for.loan",
                errorMessage);/*from  www  .  j a v  a  2s . c  o m*/
    }

    if (loanTransaction.isNotZero(loanCurrency())) {
        this.loanTransactions.add(loanTransaction);
    }

    if (loanTransaction.isNotRefundForActiveLoan()) {
        final String errorMessage = "A transaction of type refund was expected but not received.";
        throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.refund.transaction",
                errorMessage);
    }

    final LocalDate loanTransactionDate = loanTransaction.getTransactionDate();
    if (loanTransactionDate.isBefore(getDisbursementDate())) {
        final String errorMessage = "The transaction date cannot be before the loan disbursement date: "
                + getApprovedOnDate().toString();
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.before.disbursement.date",
                errorMessage, loanTransactionDate, getDisbursementDate());
    }

    if (loanTransactionDate.isAfter(DateUtils.getLocalDateOfTenant())) {
        final String errorMessage = "The transaction date cannot be in the future.";
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.a.future.date", errorMessage,
                loanTransactionDate);
    }

    if (this.loanProduct.isMultiDisburseLoan() && adjustedTransaction == null) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
            .determineProcessor(this.transactionProcessingStrategy);

    // If is a refund
    if (adjustedTransaction == null) {
        loanRepaymentScheduleTransactionProcessor.handleRefund(loanTransaction, getCurrency(),
                this.repaymentScheduleInstallments, charges());
    } else {
        final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
        changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
                getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(),
                this.repaymentScheduleInstallments, charges());
        for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                .getNewTransactionMappings().entrySet()) {
            mapEntry.getValue().updateLoan(this);
        }

    }

    updateLoanSummaryDerivedFields();

    doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);

    return changedTransactionDetail;
}

From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java

private ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction(
        final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine,
        final LoanTransaction adjustedTransaction, final ScheduleGeneratorDTO scheduleGeneratorDTO,
        final AppUser currentUser) {

    ChangedTransactionDetail changedTransactionDetail = null;

    LoanStatus statusEnum = null;/*  w  w  w  .  j  a v a2 s .  co m*/

    LocalDate recalculateFrom = loanTransaction.getTransactionDate();
    if (adjustedTransaction != null && adjustedTransaction.getTransactionDate().isBefore(recalculateFrom)) {
        recalculateFrom = adjustedTransaction.getTransactionDate();
    }

    if (loanTransaction.isRecoveryRepayment()) {
        statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT,
                LoanStatus.fromInt(this.loanStatus));
    } else {
        statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
                LoanStatus.fromInt(this.loanStatus));
    }

    this.loanStatus = statusEnum.getValue();

    loanTransaction.updateLoan(this);

    final boolean isTransactionChronologicallyLatest = isChronologicallyLatestRepaymentOrWaiver(loanTransaction,
            this.loanTransactions);

    if (loanTransaction.isNotZero(loanCurrency())) {
        this.loanTransactions.add(loanTransaction);
    }

    if (loanTransaction.isNotRepayment() && loanTransaction.isNotWaiver()
            && loanTransaction.isNotRecoveryRepayment()) {
        final String errorMessage = "A transaction of type repayment or recovery repayment or waiver was expected but not received.";
        throw new InvalidLoanTransactionTypeException("transaction",
                "is.not.a.repayment.or.waiver.or.recovery.transaction", errorMessage);
    }

    final LocalDate loanTransactionDate = loanTransaction.getTransactionDate();
    if (loanTransactionDate.isBefore(getDisbursementDate())) {
        final String errorMessage = "The transaction date cannot be before the loan disbursement date: "
                + getApprovedOnDate().toString();
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.before.disbursement.date",
                errorMessage, loanTransactionDate, getDisbursementDate());
    }

    if (loanTransactionDate.isAfter(DateUtils.getLocalDateOfTenant())) {
        final String errorMessage = "The transaction date cannot be in the future.";
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.a.future.date", errorMessage,
                loanTransactionDate);
    }

    if (loanTransaction.isInterestWaiver()) {
        Money totalInterestOutstandingOnLoan = getTotalInterestOutstandingOnLoan();
        if (adjustedTransaction != null) {
            totalInterestOutstandingOnLoan = totalInterestOutstandingOnLoan
                    .plus(adjustedTransaction.getAmount(loanCurrency()));
        }
        if (loanTransaction.getAmount(loanCurrency()).isGreaterThan(totalInterestOutstandingOnLoan)) {
            final String errorMessage = "The amount of interest to waive cannot be greater than total interest outstanding on loan.";
            throw new InvalidLoanStateTransitionException("waive.interest",
                    "amount.exceeds.total.outstanding.interest", errorMessage,
                    loanTransaction.getAmount(loanCurrency()), totalInterestOutstandingOnLoan.getAmount());
        }
    }

    if (this.loanProduct.isMultiDisburseLoan() && adjustedTransaction == null) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
            .determineProcessor(this.transactionProcessingStrategy);

    final LoanRepaymentScheduleInstallment currentInstallment = fetchLoanRepaymentScheduleInstallment(
            loanTransaction.getTransactionDate());
    boolean reprocess = true;

    if (isTransactionChronologicallyLatest && adjustedTransaction == null
            && loanTransaction.getTransactionDate().isEqual(LocalDate.now()) && currentInstallment != null
            && currentInstallment.getTotalOutstanding(getCurrency())
                    .isEqualTo(loanTransaction.getAmount(getCurrency()))) {
        reprocess = false;
    }

    if (isTransactionChronologicallyLatest && adjustedTransaction == null
            && (!reprocess || !this.repaymentScheduleDetail().isInterestRecalculationEnabled())) {
        loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(),
                this.repaymentScheduleInstallments, charges());
        reprocess = false;
        if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            if (currentInstallment == null || currentInstallment.isNotFullyPaidOff()) {
                reprocess = true;
            } else {
                final LoanRepaymentScheduleInstallment nextInstallment = fetchRepaymentScheduleInstallment(
                        currentInstallment.getInstallmentNumber() + 1);
                if (nextInstallment != null
                        && nextInstallment.getTotalPaidInAdvance(getCurrency()).isGreaterThanZero()) {
                    reprocess = true;
                }
            }
        }
    }
    if (reprocess) {
        if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
        }
        final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
        changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
                getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(),
                this.repaymentScheduleInstallments, charges());
        for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                .getNewTransactionMappings().entrySet()) {
            mapEntry.getValue().updateLoan(this);
        }
        /***
         * Commented since throwing exception if external id present for one
         * of the transactions. for this need to save the reversed
         * transactions first and then new transactions.
         */
        this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values());
    }

    updateLoanSummaryDerivedFields();

    /**
     * FIXME: Vishwas, skipping post loan transaction checks for Loan
     * recoveries
     **/
    if (loanTransaction.isNotRecoveryRepayment()) {
        doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
    }

    if (this.loanProduct.isMultiDisburseLoan()) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0
                && this.repaymentScheduleDetail().getPrincipal().minus(totalDisbursed).isGreaterThanZero()) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    if (changedTransactionDetail != null) {
        this.loanTransactions.removeAll(changedTransactionDetail.getNewTransactionMappings().values());
    }
    return changedTransactionDetail;
}

From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java

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

    if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule
            || isEmiAmountChanged) {
        regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
    }
}

From source file:com.ugam.collage.plus.service.people_count.impl.PeopleAccountingServiceImpl.java

/**
 * @param empcntClientProjectDataList//from ww  w  .ja  v  a2  s .  c  om
 * @param empClientProjectTeamStructList
 * @param employee
 * @param month
 * @param year
 * @param costCentre
 * @param countType
 * @param allignedTimeZero
 * @param assistedTimeZero
 * @param apportionedTimeZero
 * @param allignedTimeOne
 * @param totalTimeOne
 * @return
 */

private void getMultipleProjectDetail(List<EmpcntClientProjectData> empOpenCntClientProjectDataList,
        List<EmpcntClientProjectData> empCloseCntClientProjectDataList,
        List<EmpClientProjectTeamStruct> empClientProjectTeamStructList, EmployeeMaster employee,
        TabMonth month, TabYear year, CostCentre costCentre, CountClassification countType,
        BigDecimal allignedTimeZero, BigDecimal assistedTimeZero, BigDecimal apportionedTimeZero,
        BigDecimal allignedTimeOne, BigDecimal totalTimeOne, Integer countTypeId,
        Map<String, EmployeePcTagsTeamStruct> employeePcTagsTeamStructMap) {

    logger.debug("<====getMultipleProjectDetail START====>");
    Integer employeeId = employee.getEmployeeId();
    Integer yearId = year.getYearId();
    Integer monthId = month.getMonthId();
    String costCentreId = costCentre.getCostCentreId();
    BigDecimal deviderHour = new BigDecimal(Constants.TOTAL_WORKING_HOURS);
    logger.debug("getMultipleProjectDetail parameter===>" + employeeId + "::" + yearId + "::" + monthId + "::"
            + costCentreId + "::" + deviderHour);

    // Get project details
    Map<Integer, EmpClientProjectTeamStruct> employeeProjectIds = new HashMap<Integer, EmpClientProjectTeamStruct>();

    Map<Integer, EmpClientProjectTeamStruct> validEmployeeProjectIds = new HashMap<Integer, EmpClientProjectTeamStruct>();

    for (EmpClientProjectTeamStruct empClientProjectTeamStructThree : empClientProjectTeamStructList) {
        employeeProjectIds.put(empClientProjectTeamStructThree.getProjectMaster().getProjectId(),
                empClientProjectTeamStructThree);
    }

    validEmployeeProjectIds.putAll(employeeProjectIds);
    // logger.debug("validEmployeeProjectIds 1:size===>" +
    // validEmployeeProjectIds.size());

    // check in revenue table
    for (Integer key : employeeProjectIds.keySet()) {
        EmpClientProjectTeamStruct mapValues = employeeProjectIds.get(key);
        List<CollageProjectRevenue> listValues = collageProjectRevenueDao
                .findByYearIdMonthIdProjectIdCostCentreId(mapValues.getTabYear().getYearId(),
                        mapValues.getTabMonth().getMonthId(), mapValues.getProjectMaster().getProjectId(),
                        costCentre.getCostCentreId());
        if (listValues.isEmpty()) {
            validEmployeeProjectIds.remove(key);
        }
    }
    // logger.debug("validEmployeeProjectIds 2:size===>" +
    // validEmployeeProjectIds.size());
    // For all invalid projects calculate count zero
    if (validEmployeeProjectIds.isEmpty()) {
        getZeroProjectsDetail(yearId, monthId, costCentreId, empOpenCntClientProjectDataList,
                empCloseCntClientProjectDataList, employee, month, year, costCentre, countType,
                allignedTimeZero, assistedTimeZero, totalTimeOne, totalTimeOne, countTypeId,
                employeePcTagsTeamStructMap);
    }
    // Get list of project from execution data for that employee
    List<Integer> projectIdList = executionDataDao.findByPersonYearMonthCostCentre(employeeId, yearId, monthId,
            costCentreId);
    // logger.debug("execution data projects===>" + projectIdList.size());

    // If List is empty
    if (projectIdList.isEmpty()) {
        // logger.debug("Contain InValid projects (: Find by Revenue)===>");

        Map<Integer, BigDecimal> projectRevenueMap = new HashMap<Integer, BigDecimal>();
        BigDecimal sumOfRevenue = BigDecimal.ZERO;

        List<Object[]> collageProjectRevenueList = collageProjectRevenueDao.findByCostCentreIdYearIdMonthId(
                costCentre.getCostCentreId(), year.getYearId(), month.getMonthId());

        for (Object[] collageProjectRevenue : collageProjectRevenueList) {
            Integer projectId = (Integer) collageProjectRevenue[0];
            BigDecimal revenue = (BigDecimal) collageProjectRevenue[1];
            projectRevenueMap.put(projectId, revenue);
        }
        // logger.debug("projectRevenueMap size===>" +
        // projectRevenueMap.size());

        for (Integer key : projectRevenueMap.keySet()) {
            sumOfRevenue = sumOfRevenue.add(projectRevenueMap.get(key));
        }
        logger.debug("sumOfRevenue===>" + sumOfRevenue);

        for (Integer projectId : validEmployeeProjectIds.keySet()) {
            EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
            BigDecimal revenue = projectRevenueMap.get(projectId);
            logger.debug("revenue===>" + revenue);
            BigDecimal projectRevenueCount = revenue.divide(sumOfRevenue, 2, RoundingMode.HALF_EVEN);
            projectRevenueCount = projectRevenueCount.setScale(2, RoundingMode.CEILING);
            // logger.debug("685 empOpenCntClientProjectData ProjectId:Revenue===>"+projectId+" : "
            // + projectRevenueCount);
            EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                    mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                    costCentre, projectRevenueCount, BigDecimal.ZERO, BigDecimal.ZERO, projectRevenueCount);
            if (countTypeId == 1) {
                empOpenCntClientProjectDataList.add(empcntClientProjectData);
            }
            if (countTypeId == 2) {
                empCloseCntClientProjectDataList.add(empcntClientProjectData);
            }
        }
    } else {
        // logger.debug("Else Contain Valid projects===>");
        Integer validEmployeeProjectCount = validEmployeeProjectIds.size();
        // Get valid projects list=>project is both revenue data and
        // execution data
        Set<Integer> validAllProjects = new HashSet<Integer>();
        for (Integer projectId : projectIdList) {
            List<CollageProjectRevenue> listValues = collageProjectRevenueDao
                    .findByYearIdMonthIdProjectIdCostCentreId(yearId, monthId, projectId, costCentreId);
            if (!listValues.isEmpty()) {
                validAllProjects.add(projectId);
            }

        }
        Integer validAllProjectCount = validAllProjects.size();
        // logger.debug("validAllProjects :size===>" +
        // validAllProjects.size());
        // Total hour worked by an Employee
        List<BigDecimal> toatalHours = executionDataDao.findByPersonIdYearIdMonthIdCostCentreId(employeeId,
                yearId, monthId, costCentreId);
        BigDecimal toatlTime = toatalHours.get(0);
        // logger.debug("ToatalHours===>" + toatlTime);

        // Separate assigned projects from execution data projects
        Map<Integer, BigDecimal> assignedProjects = new HashMap<Integer, BigDecimal>();
        Map<Integer, BigDecimal> unAssignedProjects = new HashMap<Integer, BigDecimal>();
        List<Object[]> allProjectTimeList = executionDataDao
                .findByEmployeeIdYearIdMonthIdCostCentreId(employeeId, yearId, monthId, costCentreId);
        for (Object[] result : allProjectTimeList) {
            Integer projectId = (Integer) result[0];
            BigDecimal hour = (BigDecimal) result[1];
            Integer companyId = (Integer) result[2];
            if (validEmployeeProjectIds.containsKey(projectId) && validAllProjects.contains(projectId)) {
                // logger.debug("UnAssignedProjects===>" +
                // projectId+"::"+hour+"::"+companyId);
                assignedProjects.put(projectId, hour);
            }
            if (!validEmployeeProjectIds.containsKey(projectId) && validAllProjects.contains(projectId)) {
                // logger.debug("assignedProjects===>" +
                // projectId+"::"+hour+"::"+companyId);
                unAssignedProjects.put(projectId, hour);
            }
        }

        if (validEmployeeProjectCount == validAllProjectCount
                && validAllProjects.containsAll(validEmployeeProjectIds.keySet())
                && unAssignedProjects.isEmpty()) {

            // logger.debug("validEmployeeProjectCount==validAllProjectCount :(Only in assigned projects)");
            for (Integer key : assignedProjects.keySet()) {
                // Get time spent on each project by employee id
                Integer projectId = key;
                BigDecimal timeByProject = assignedProjects.get(key);
                EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                // logger.debug("744 : Worked hours (Only in assigned projects) 1===>"+timeByProject+
                // " : "+toatlTime);
                BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                // logger.debug("745: Worked hours (Only in assigned projects) 2===>"+workedHours);
                EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                        mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                        costCentre, workedHours, assistedTimeZero, apportionedTimeZero, workedHours);
                if (countTypeId == 1) {
                    empOpenCntClientProjectDataList.add(empcntClientProjectData);
                }
                if (countTypeId == 2) {
                    empCloseCntClientProjectDataList.add(empcntClientProjectData);
                }
            }

        } else if (!assignedProjects.isEmpty() && !unAssignedProjects.isEmpty()) {
            // logger.debug("validEmployeeProjectCount!=validAllProjectCount :(Both in assigned and unassigned projects)");
            if (toatlTime.compareTo(new BigDecimal(Constants.TOTAL_WORKING_HOURS)) >= 0) {
                // logger.debug("Worked hours===> >=168");
                for (Integer key : assignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = assignedProjects.get(key);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("768: Aligned hours (Both in assigned and unassigned projects) 1===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, workedHours, assistedTimeZero, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("787: Assisted hours (Both in assigned and unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            } else {
                // logger.debug("Worked hours===> <168");
                BigDecimal totalUnAssingnedHours = BigDecimal.ZERO;
                BigDecimal assingnedHours = BigDecimal.ZERO;
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    // logger.debug("Project Id===>"+key);
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    BigDecimal workedHours = timeByProject.divide(deviderHour, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    totalUnAssingnedHours = totalUnAssingnedHours.add(workedHours);
                    // Assign to assisted count for unAssignedProjects
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    // logger.debug("811: Assisted hours (Both in assigned and unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                totalUnAssingnedHours = BigDecimal.ONE.subtract(totalUnAssingnedHours);
                // logger.debug("totalUnAssingnedHours===> "+totalUnAssingnedHours);
                for (Map.Entry<Integer, BigDecimal> entry : assignedProjects.entrySet()) {
                    assingnedHours = assingnedHours.add(entry.getValue());
                }
                // logger.debug("Aligned Hours===> "+assingnedHours);
                for (Integer key : assignedProjects.keySet()) {
                    Integer projectId = key;
                    BigDecimal timeByProject = assignedProjects.get(key);
                    // logger.debug("831 :projectId : timeByProject===> "+projectId+" : "+timeByProject);
                    EmpClientProjectTeamStruct mapValues = validEmployeeProjectIds.get(projectId);
                    BigDecimal averageWorkedHours = timeByProject.divide(assingnedHours, 2,
                            RoundingMode.HALF_EVEN);
                    // logger.debug("834 :averageWorkedHours : assingnedHours===> "+averageWorkedHours+" : "+assingnedHours);
                    BigDecimal actualWorkedHours = averageWorkedHours.multiply(totalUnAssingnedHours);
                    actualWorkedHours = actualWorkedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("836: actualWorkedHours : totalUnAssingnedHours 2===>"+actualWorkedHours+" : "+totalUnAssingnedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            mapValues.getCompanyMaster(), countType, month, mapValues.getProjectMaster(), year,
                            costCentre, actualWorkedHours, assistedTimeZero, apportionedTimeZero,
                            actualWorkedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            }
        } else if (assignedProjects.isEmpty() && !unAssignedProjects.isEmpty()) {
            // logger.debug("Only in unassigned projects===>");
            if (toatlTime.compareTo(new BigDecimal(Constants.TOTAL_WORKING_HOURS)) >= 0) {
                // logger.debug(" unassigned projects Worked hours===> >=168");
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    BigDecimal workedHours = timeByProject.divide(toatlTime, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    // logger.debug("860: Assisted hours (Both in assigned and unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
            } else {
                // logger.debug("unassigned projects Worked hours===> <168");
                BigDecimal totalUnAssingnedHours = BigDecimal.ZERO;
                BigDecimal assingnedHours = BigDecimal.ZERO;
                for (Integer key : unAssignedProjects.keySet()) {
                    // Get time spent on each project by employee id
                    Integer projectId = key;
                    BigDecimal timeByProject = unAssignedProjects.get(key);
                    BigDecimal workedHours = timeByProject.divide(deviderHour, 2, RoundingMode.HALF_EVEN);
                    workedHours = workedHours.setScale(2, RoundingMode.CEILING);
                    totalUnAssingnedHours = totalUnAssingnedHours.add(workedHours);
                    // Assign to assisted count for unAssignedProjects
                    List<ProjectMaster> projectList = projectMasterDao.findByProjectId(projectId);
                    ProjectMaster projectMaster = projectList.get(0);
                    CompanyMaster companyMaster = projectMaster.getCompanyMaster();
                    // logger.debug("884: Assisted hours in unassigned projects) 2===>"+workedHours);
                    EmpcntClientProjectData empcntClientProjectData = new EmpcntClientProjectData(employee,
                            companyMaster, countType, month, projectMaster, year, costCentre,
                            apportionedTimeZero, workedHours, apportionedTimeZero, workedHours);
                    if (countTypeId == 1) {
                        empOpenCntClientProjectDataList.add(empcntClientProjectData);
                    }
                    if (countTypeId == 2) {
                        empCloseCntClientProjectDataList.add(empcntClientProjectData);
                    }
                }
                // logger.debug("totalUnAssingnedHours===> "+totalUnAssingnedHours);
                if (totalUnAssingnedHours.compareTo(BigDecimal.ONE) == -1) {
                    BigDecimal remainProportion = BigDecimal.ONE.subtract(totalUnAssingnedHours);
                    getRevenueCountProportion(empOpenCntClientProjectDataList, empCloseCntClientProjectDataList,
                            employee, month, year, costCentre, countType, remainProportion, unAssignedProjects,
                            countTypeId, employeePcTagsTeamStructMap);
                }
            }
        }

    }
    // logger.debug("<====getMultipleProjectDetail END====>");
}

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

private ChangedTransactionDetail handleRefundTransaction(final LoanTransaction loanTransaction,
        final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) {

    ChangedTransactionDetail changedTransactionDetail = null;

    final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND,
            LoanStatus.fromInt(this.loanStatus));
    this.loanStatus = statusEnum.getValue();

    loanTransaction.updateLoan(this);

    // final boolean isTransactionChronologicallyLatest =
    // isChronologicallyLatestRefund(loanTransaction,
    // this.loanTransactions);

    if (status().isOverpaid() || status().isClosed()) {

        final String errorMessage = "This refund option is only for active loans ";
        throw new InvalidLoanStateTransitionException("transaction", "is.exceeding.overpaid.amount",
                errorMessage, this.totalOverpaid, loanTransaction.getAmount(getCurrency()).getAmount());

    } else if (this.getTotalPaidInRepayments().isZero()) {
        final String errorMessage = "Cannot refund when no payment has been made";
        throw new InvalidLoanStateTransitionException("transaction", "no.payment.yet.made.for.loan",
                errorMessage);// w w w  .  j av a 2 s.c  o m
    }

    if (loanTransaction.isNotZero(loanCurrency())) {
        addLoanTransaction(loanTransaction);
    }

    if (loanTransaction.isNotRefundForActiveLoan()) {
        final String errorMessage = "A transaction of type refund was expected but not received.";
        throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.refund.transaction",
                errorMessage);
    }

    final LocalDate loanTransactionDate = loanTransaction.getTransactionDate();
    if (loanTransactionDate.isBefore(getDisbursementDate())) {
        final String errorMessage = "The transaction date cannot be before the loan disbursement date: "
                + getApprovedOnDate().toString();
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.before.disbursement.date",
                errorMessage, loanTransactionDate, getDisbursementDate());
    }

    if (loanTransactionDate.isAfter(DateUtils.getLocalDateOfTenant())) {
        final String errorMessage = "The transaction date cannot be in the future.";
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.a.future.date", errorMessage,
                loanTransactionDate);
    }

    if (this.loanProduct.isMultiDisburseLoan() && adjustedTransaction == null) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
            .determineProcessor(this.transactionProcessingStrategy);

    // If is a refund
    if (adjustedTransaction == null) {
        loanRepaymentScheduleTransactionProcessor.handleRefund(loanTransaction, getCurrency(),
                getRepaymentScheduleInstallments(), charges());
    } else {
        final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
        changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
                getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(),
                getRepaymentScheduleInstallments(), charges());
        for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                .getNewTransactionMappings().entrySet()) {
            mapEntry.getValue().updateLoan(this);
        }

    }

    updateLoanSummaryDerivedFields();

    doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);

    return changedTransactionDetail;
}

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

private ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction(
        final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine,
        final LoanTransaction adjustedTransaction, final ScheduleGeneratorDTO scheduleGeneratorDTO,
        final AppUser currentUser) {

    ChangedTransactionDetail changedTransactionDetail = null;

    LoanStatus statusEnum = null;/*from   w ww.j  a v a  2 s .  co  m*/

    LocalDate recalculateFrom = loanTransaction.getTransactionDate();
    if (adjustedTransaction != null && adjustedTransaction.getTransactionDate().isBefore(recalculateFrom)) {
        recalculateFrom = adjustedTransaction.getTransactionDate();
    }

    if (loanTransaction.isRecoveryRepayment()) {
        statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT,
                LoanStatus.fromInt(this.loanStatus));
    } else {
        statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
                LoanStatus.fromInt(this.loanStatus));
    }

    this.loanStatus = statusEnum.getValue();

    loanTransaction.updateLoan(this);

    final boolean isTransactionChronologicallyLatest = isChronologicallyLatestRepaymentOrWaiver(loanTransaction,
            getLoanTransactions());

    if (loanTransaction.isNotZero(loanCurrency())) {
        addLoanTransaction(loanTransaction);
    }

    if (loanTransaction.isNotRepayment() && loanTransaction.isNotWaiver()
            && loanTransaction.isNotRecoveryRepayment()) {
        final String errorMessage = "A transaction of type repayment or recovery repayment or waiver was expected but not received.";
        throw new InvalidLoanTransactionTypeException("transaction",
                "is.not.a.repayment.or.waiver.or.recovery.transaction", errorMessage);
    }

    final LocalDate loanTransactionDate = loanTransaction.getTransactionDate();
    if (loanTransactionDate.isBefore(getDisbursementDate())) {
        final String errorMessage = "The transaction date cannot be before the loan disbursement date: "
                + getApprovedOnDate().toString();
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.before.disbursement.date",
                errorMessage, loanTransactionDate, getDisbursementDate());
    }

    if (loanTransactionDate.isAfter(DateUtils.getLocalDateOfTenant())) {
        final String errorMessage = "The transaction date cannot be in the future.";
        throw new InvalidLoanStateTransitionException("transaction", "cannot.be.a.future.date", errorMessage,
                loanTransactionDate);
    }

    if (loanTransaction.isInterestWaiver()) {
        Money totalInterestOutstandingOnLoan = getTotalInterestOutstandingOnLoan();
        if (adjustedTransaction != null) {
            totalInterestOutstandingOnLoan = totalInterestOutstandingOnLoan
                    .plus(adjustedTransaction.getAmount(loanCurrency()));
        }
        if (loanTransaction.getAmount(loanCurrency()).isGreaterThan(totalInterestOutstandingOnLoan)) {
            final String errorMessage = "The amount of interest to waive cannot be greater than total interest outstanding on loan.";
            throw new InvalidLoanStateTransitionException("waive.interest",
                    "amount.exceeds.total.outstanding.interest", errorMessage,
                    loanTransaction.getAmount(loanCurrency()), totalInterestOutstandingOnLoan.getAmount());
        }
    }

    if (this.loanProduct.isMultiDisburseLoan() && adjustedTransaction == null) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
            .determineProcessor(this.transactionProcessingStrategy);

    final LoanRepaymentScheduleInstallment currentInstallment = fetchLoanRepaymentScheduleInstallment(
            loanTransaction.getTransactionDate());
    boolean reprocess = true;

    if (!isForeclosure() && isTransactionChronologicallyLatest && adjustedTransaction == null
            && loanTransaction.getTransactionDate().isEqual(DateUtils.getLocalDateOfTenant())
            && currentInstallment != null && currentInstallment.getTotalOutstanding(getCurrency())
                    .isEqualTo(loanTransaction.getAmount(getCurrency()))) {
        reprocess = false;
    }

    if (isTransactionChronologicallyLatest && adjustedTransaction == null
            && (!reprocess || !this.repaymentScheduleDetail().isInterestRecalculationEnabled())
            && !isForeclosure()) {
        loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(),
                getRepaymentScheduleInstallments(), charges());
        reprocess = false;
        if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            if (currentInstallment == null || currentInstallment.isNotFullyPaidOff()) {
                reprocess = true;
            } else {
                final LoanRepaymentScheduleInstallment nextInstallment = fetchRepaymentScheduleInstallment(
                        currentInstallment.getInstallmentNumber() + 1);
                if (nextInstallment != null
                        && nextInstallment.getTotalPaidInAdvance(getCurrency()).isGreaterThanZero()) {
                    reprocess = true;
                }
            }
        }
    }
    if (reprocess) {
        if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser);
        }
        final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
        changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
                getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(),
                getRepaymentScheduleInstallments(), charges());
        for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                .getNewTransactionMappings().entrySet()) {
            mapEntry.getValue().updateLoan(this);
        }
        /***
         * Commented since throwing exception if external id present for one
         * of the transactions. for this need to save the reversed
         * transactions first and then new transactions.
         */
        this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values());
    }

    updateLoanSummaryDerivedFields();

    /**
     * FIXME: Vishwas, skipping post loan transaction checks for Loan
     * recoveries
     **/
    if (loanTransaction.isNotRecoveryRepayment()) {
        doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
    }

    if (this.loanProduct.isMultiDisburseLoan()) {
        BigDecimal totalDisbursed = getDisbursedAmount();
        if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0
                && this.repaymentScheduleDetail().getPrincipal().minus(totalDisbursed).isGreaterThanZero()) {
            final String errorMessage = "The transaction cannot be done before the loan disbursement: "
                    + getApprovedOnDate().toString();
            throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement",
                    errorMessage);
        }
    }

    if (changedTransactionDetail != null) {
        this.loanTransactions.removeAll(changedTransactionDetail.getNewTransactionMappings().values());
    }
    return changedTransactionDetail;
}