Example usage for java.math BigDecimal subtract

List of usage examples for java.math BigDecimal subtract

Introduction

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

Prototype

public BigDecimal subtract(BigDecimal subtrahend) 

Source Link

Document

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

Usage

From source file:org.egov.works.web.actions.estimate.EstimatePDFGenerator.java

private PdfPTable createBudgetDetailsForEstimateTable(final AbstractEstimate estimate)
        throws DocumentException {
    try {/*  w w w . ja va  2  s.  co  m*/

        final PdfPTable estBudgetDetailsTable = new PdfPTable(4);
        estBudgetDetailsTable.setWidthPercentage(75);
        estBudgetDetailsTable.setWidths(new float[] { 0.6f, 1f, 0.5f, 1f });

        BigDecimal totalGrant;
        BigDecimal budgetAvailable;
        BigDecimal balOnHand;
        BigDecimal amtAppropriated = BigDecimal.ZERO;
        BigDecimal totGrantafterMultiFactor = BigDecimal.ZERO;

        BigDecimal totalUtilizedAmt;
        BigDecimal amtAppropriatedsofar = BigDecimal.ZERO;
        worksService.getAccountdetailtypeByName("DEPOSITCODE");
        AbstractEstimateAppropriation latestAbstractEstimateAppropriation;

        if (abstractEstimateAppropriationList != null && !abstractEstimateAppropriationList.isEmpty()) {
            latestAbstractEstimateAppropriation = abstractEstimateAppropriationList
                    .get(abstractEstimateAppropriationList.size() - 1);

            if (latestAbstractEstimateAppropriation != null)
                if (estimate.getDepositCode() == null) {
                    if (latestAbstractEstimateAppropriation.getBudgetUsage().getConsumedAmount() != 0) {
                        final Department dept = getDeptFromBudgtAppropriationNo(
                                latestAbstractEstimateAppropriation.getBudgetUsage().getAppropriationnumber());
                        totalGrant = abstractEstimateService.getTotalGrantForYearAsOnDate(
                                estimate.getFinancialDetails().get(0),
                                latestAbstractEstimateAppropriation.getBudgetUsage().getFinancialYearId()
                                        .longValue(),
                                Integer.parseInt(dept.getId().toString()),
                                latestAbstractEstimateAppropriation.getBudgetUsage().getUpdatedTime());
                        final BigDecimal planningBudgetPerc = abstractEstimateService
                                .getPlanningBudgetPercentage(estimate.getFinancialDetails().get(0),
                                        latestAbstractEstimateAppropriation.getBudgetUsage()
                                                .getFinancialYearId().longValue(),
                                        Integer.parseInt(dept.getId().toString()));
                        if (planningBudgetPerc != null && planningBudgetPerc.compareTo(BigDecimal.ZERO) != 0) {
                            totGrantafterMultiFactor = totalGrant
                                    .multiply(planningBudgetPerc.divide(new BigDecimal(100)));
                            appValue = planningBudgetPerc.divide(new BigDecimal(100)).toString();
                        }

                        budgetAvailable = latestAbstractEstimateAppropriation.getBalanceAvailable();
                        balOnHand = budgetAvailable.add(new BigDecimal(
                                latestAbstractEstimateAppropriation.getBudgetUsage().getConsumedAmount()));
                        amtAppropriated = totGrantafterMultiFactor.subtract(balOnHand);
                    }
                } else if (latestAbstractEstimateAppropriation.getDepositWorksUsage().getConsumedAmount()
                        .doubleValue() != 0) {
                    totalUtilizedAmt = depositWorksUsageService.getTotalUtilizedAmountForDepositWorks(
                            latestAbstractEstimateAppropriation.getAbstractEstimate().getFinancialDetails()
                                    .get(0),
                            latestAbstractEstimateAppropriation.getDepositWorksUsage().getCreatedDate());
                    if (totalUtilizedAmt == null)
                        totalUtilizedAmt = BigDecimal.ZERO;
                    amtAppropriatedsofar = totalUtilizedAmt.subtract(
                            latestAbstractEstimateAppropriation.getDepositWorksUsage().getConsumedAmount());
                }
        }
        addRow(estBudgetDetailsTable, true, centerPara("Estimate Date"),
                centerPara(DateUtils.getFormattedDate(estimate.getEstimateDate(), "dd/MM/yyyy")),
                centerPara("Fund"), centerPara(estimate.getFinancialDetails().isEmpty() ? ""
                        : estimate.getFinancialDetails().get(0).getFund().getName()));
        if (estimate.getDepositCode() == null) {
            addRow(estBudgetDetailsTable, true, centerPara("Function "),
                    centerPara(estimate.getFinancialDetails().isEmpty() ? ""
                            : estimate.getFinancialDetails().get(0).getFunction().getName()),
                    centerPara("Budget Head"), centerPara(estimate.getFinancialDetails().isEmpty() ? ""
                            : estimate.getFinancialDetails().get(0).getBudgetGroup().getName()));
            addRow(estBudgetDetailsTable, true, centerPara("Amount Appropriated so far"),
                    centerPara(amtAppropriated == null ? "" : toCurrency(amtAppropriated.doubleValue())),
                    centerPara("Estimate Amount"),
                    centerPara(toCurrency(estimate.getTotalAmount().getValue())));
        } else {
            addRow(estBudgetDetailsTable, true, centerPara("Function "),
                    centerPara(estimate.getFinancialDetails().isEmpty() ? ""
                            : estimate.getFinancialDetails().get(0).getFunction().getName()),
                    centerPara("Deposit COA/Deposit Code"),
                    centerPara(estimate.getFinancialDetails().isEmpty() ? ""
                            : estimate.getFinancialDetails().get(0).getCoa().getGlcode().concat("-")
                                    .concat(estimate.getFinancialDetails().get(0).getCoa().getName())
                                    .concat(" / ").concat(estimate.getDepositCode().getCode())));
            addRow(estBudgetDetailsTable, true, centerPara("Amount Appropriated so far"),
                    centerPara(
                            amtAppropriatedsofar == null ? "" : toCurrency(amtAppropriatedsofar.doubleValue())),
                    centerPara("Estimate Amount"),
                    makePara(toCurrency(estimate.getTotalAmount().getValue()), Element.ALIGN_RIGHT));
        }

        return estBudgetDetailsTable;
    } catch (final Exception e) {
        throw new ApplicationRuntimeException("Exception occured while estimate details method 2 " + e);
    }
}

From source file:org.egov.ptis.domain.service.property.PropertyExternalService.java

public AssessmentDetails getDuesForProperty(final HttpServletRequest request, String assessmentNo,
        String oldAssessmentNo) {
    AssessmentDetails assessmentDetails = new AssessmentDetails();
    BasicProperty basicProperty = fetchBasicProperty(assessmentNo, oldAssessmentNo);
    if (basicProperty != null) {
        assessmentDetails.setPropertyID(basicProperty.getUpicNo());
        assessmentDetails.setOldAssessmentNo(basicProperty.getOldMuncipalNum());
        assessmentDetails.setPropertyAddress(basicProperty.getAddress().toString());
        assessmentDetails.setOwners(basicProperty.getFullOwnerName());
        assessmentDetails.setStatus(basicProperty.getActive());
        Property property = basicProperty.getProperty();
        if (property != null) {
            assessmentDetails.setExempted(property.getIsExemptedFromTax());
            if (!property.getIsExemptedFromTax()) {
                Map<String, BigDecimal> dmdCollMap = ptDemandDAO.getDemandIncludingPenaltyCollMap(property);
                if (!dmdCollMap.isEmpty()) {
                    BigDecimal totalDemand = dmdCollMap.get(ARR_DMD_STR)
                            .add(dmdCollMap.get(CURR_FIRSTHALF_DMD_STR))
                            .add(dmdCollMap.get(CURR_SECONDHALF_DMD_STR));
                    BigDecimal totalColl = dmdCollMap.get(ARR_COLL_STR)
                            .add(dmdCollMap.get(CURR_FIRSTHALF_COLL_STR))
                            .add(dmdCollMap.get(CURR_SECONDHALF_COLL_STR));
                    assessmentDetails.setPropertyDue(totalDemand.subtract(totalColl));
                }//from ww w.ja v  a2s. co  m
            }
        }
        String restURL = format(PropertyTaxConstants.WTMS_TAXDUE_RESTURL,
                WebUtils.extractRequestDomainURL(request, false), basicProperty.getUpicNo());
        Map<String, Object> taxDetails = simpleRestClient.getRESTResponseAsMap(restURL);
        if (!taxDetails.isEmpty()) {
            assessmentDetails.setWaterTaxDue(BigDecimal.valueOf((double) taxDetails.get(WATER_TAX_DUES)));
            assessmentDetails.setConnectionCount(
                    Double.valueOf(taxDetails.get("connectionCount").toString()).intValue());
        }
        restURL = format(PropertyTaxConstants.STMS_TAXDUE_RESTURL,
                WebUtils.extractRequestDomainURL(request, false), basicProperty.getUpicNo());
        taxDetails = simpleRestClient.getRESTResponseAsMap(restURL);
        if (!taxDetails.isEmpty())
            assessmentDetails.setSewerageDue(BigDecimal.valueOf((double) taxDetails.get("totalTaxDue")));
    }
    return assessmentDetails;
}

From source file:org.egov.services.payment.PaymentService.java

public List<PaymentBean> getMiscBillList(final Paymentheader header) {
    if (LOGGER.isDebugEnabled())
        LOGGER.debug("Starting getMiscBillList...");
    List<PaymentBean> paymentBeanList = null;
    final Query query = getSession().createSQLQuery(
            "select mb.billvhId as billId,mb.billnumber as billNumber,mb.billdate as billDate,mb.paidto as payTo,mb.amount as netAmt,  "
                    + " mb.passedamount as passedAmt,mb.paidamount as paymentAmt,br.expendituretype as expType from miscbilldetail mb, eg_billregister br , eg_billregistermis mis "
                    + " where mb.payvhid=" + header.getVoucherheader().getId()
                    + " and br.id= mis.billid and mis.voucherheaderid=billvhid order by mb.paidto,mb.BILLDATE")
            .addScalar("billId", BigDecimalType.INSTANCE).addScalar("billNumber").addScalar("billDate")
            .addScalar("payTo").addScalar("netAmt", BigDecimalType.INSTANCE)
            .addScalar("passedAmt", BigDecimalType.INSTANCE).addScalar("paymentAmt", BigDecimalType.INSTANCE)
            .addScalar("expType").setResultTransformer(Transformers.aliasToBean(PaymentBean.class));
    paymentBeanList = query.list();/*from  w w w .j av a 2 s  .  c o  m*/
    BigDecimal earlierAmt;
    for (final PaymentBean bean : paymentBeanList) {
        bean.setIsSelected(true);
        earlierAmt = (BigDecimal) persistenceService.find(
                " select sum(paidamount) from Miscbilldetail where billVoucherHeader.id=?"
                        + " and payVoucherHeader.status not in(?,?)",
                bean.getCsBillId(), FinancialConstants.CANCELLEDVOUCHERSTATUS,
                FinancialConstants.REVERSEDVOUCHERSTATUS);
        if (earlierAmt == null)
            earlierAmt = BigDecimal.ZERO;
        bean.setEarlierPaymentAmt(earlierAmt.subtract(bean.getPaymentAmt()));
        bean.setPayableAmt(bean.getNetAmt().subtract(bean.getEarlierPaymentAmt()));
    }
    if (LOGGER.isDebugEnabled())
        LOGGER.debug("Completed getMiscBillList.");
    return paymentBeanList;
}

From source file:och.front.service.FrontAppTest.java

private void test_billing_payBill() throws Exception {

     pushToSecurityContext_SYSTEM_USER();
     try {/* www .  j  ava 2  s .c o  m*/

         BigDecimal balance = billing.getUserBalance(userId1);
         List<PaymentExt> payments = billing.getPayments(userId1, 100, 0);

         String desc = "test bill";
         BigDecimal delta = TEN;
         billing.payBill(userId1, delta, new Date(), SYSTEM_OUT_CORRECTION, desc);

         BigDecimal newBalance = billing.getUserBalance(userId1);
         assertEquals(balance.subtract(TEN).doubleValue(), newBalance.doubleValue(), 0.01);

         List<PaymentExt> newPayments = billing.getPayments(userId1, 100, 0);
         assertEquals(payments.size() + 1, newPayments.size());

         PaymentExt item = newPayments.get(0);
         assertEquals(desc, item.details);
         assertEquals(PaymentType.SYSTEM_OUT_CORRECTION, item.payType);

     } finally {
         popUserFromSecurityContext();
     }
 }

From source file:org.egov.adtax.service.AdvertisementDemandService.java

/**
 * Update demand details of current or latest year data on renewal. Assumption: There is no partial payment collected for
 * selected year./*from   ww w  .  j  a v  a  2s  .c o  m*/
 *
 * @param advertisementPermitDetail
 * @param demand
 * @return
 */
public EgDemand updateDemandOnRenewal(final AdvertisementPermitDetail advertisementPermitDetail,
        final EgDemand demand) {

    if (demand != null) {

        final List<EgDemandDetails> removableDemandDetailList = new ArrayList<>();
        final Installment installment = demand.getEgInstallmentMaster();

        BigDecimal totalDemandAmount = BigDecimal.ZERO;

        Boolean enchroachmentFeeAlreadyExistInDemand = false;

        /*
         * EgDemandReason pendingTaxReason = getDemandReasonByCodeAndInstallment(
         * AdvertisementTaxConstants.DEMANDREASON_ARREAR_ADVERTISEMENTTAX, installment);
         */
        final EgDemandReason encroachmentFeeReason = getDemandReasonByCodeAndInstallment(
                AdvertisementTaxConstants.DEMANDREASON_ENCROCHMENTFEE, installment);
        final EgDemandReason taxReason = getDemandReasonByCodeAndInstallment(
                AdvertisementTaxConstants.DEMANDREASON_ADVERTISEMENTTAX, installment);

        for (final EgDemandDetails dmdDtl : demand.getEgDemandDetails()) {
            // Assumption: tax amount is mandatory.
            if (dmdDtl.getEgDemandReason().getId() == taxReason.getId()
                    && advertisementPermitDetail.getTaxAmount().compareTo(BigDecimal.ZERO) >= 0) {
                totalDemandAmount = totalDemandAmount
                        .add(advertisementPermitDetail.getTaxAmount().subtract(dmdDtl.getAmount()));
                dmdDtl.setAmount(
                        advertisementPermitDetail.getTaxAmount().setScale(0, BigDecimal.ROUND_HALF_UP));
            }
            /*
             * if (dmdDtl.getEgDemandReason().getId() == pendingTaxReason.getId() &&
             * advertisementPermitDetail.getAdvertisement().getPendingTax()!=null &&
             * advertisementPermitDetail.getAdvertisement().getPendingTax().compareTo(BigDecimal.ZERO) > 0) { // TODO: Also
             * check whether fully collected ? totalDemandAmount =
             * totalDemandAmount.add(advertisementPermitDetail.getAdvertisement().getPendingTax().subtract(dmdDtl.getAmount())
             * ); dmdDtl.setAmount(advertisementPermitDetail.getAdvertisement().getPendingTax().setScale(0,
             * BigDecimal.ROUND_HALF_UP)); }
             */
            // Encroachment fee may not mandatory. If already part of demand
            if (dmdDtl.getEgDemandReason().getId() == encroachmentFeeReason.getId()) {
                enchroachmentFeeAlreadyExistInDemand = true;
                if (advertisementPermitDetail.getEncroachmentFee() != null
                        && advertisementPermitDetail.getEncroachmentFee().compareTo(BigDecimal.ZERO) > 0) {
                    totalDemandAmount = totalDemandAmount
                            .add(advertisementPermitDetail.getEncroachmentFee().subtract(dmdDtl.getAmount()));
                    dmdDtl.setAmount(advertisementPermitDetail.getEncroachmentFee().setScale(0,
                            BigDecimal.ROUND_HALF_UP));

                    // update encroachment fee..
                } else {
                    totalDemandAmount = totalDemandAmount.subtract(dmdDtl.getAmount());
                    // demand.removeEgDemandDetails(dmdDtl);
                    removableDemandDetailList.add(dmdDtl);
                    // delete demand detail
                }

            }
        }

        if (!enchroachmentFeeAlreadyExistInDemand && advertisementPermitDetail.getEncroachmentFee() != null
                && advertisementPermitDetail.getEncroachmentFee().compareTo(BigDecimal.ZERO) > 0) {
            demand.addEgDemandDetails(
                    createDemandDetails(advertisementPermitDetail.getEncroachmentFee(),
                            getDemandReasonByCodeAndInstallment(
                                    AdvertisementTaxConstants.DEMANDREASON_ENCROCHMENTFEE, installment),
                            BigDecimal.ZERO));
            totalDemandAmount = totalDemandAmount.add(advertisementPermitDetail.getEncroachmentFee());
        }
        for (final EgDemandDetails removableDmdDtl : removableDemandDetailList)
            demand.removeEgDemandDetails(removableDmdDtl);
        demand.addBaseDemand(totalDemandAmount.setScale(0, BigDecimal.ROUND_HALF_UP));

    }
    return demand;

}

From source file:org.egov.ptis.domain.service.property.PropertyExternalService.java

private PropertyTaxDetails getPropertyTaxDetails(final BasicProperty basicProperty, String category) {
    final PropertyTaxDetails propertyTaxDetails = new PropertyTaxDetails();
    final ErrorDetails errorDetails = new ErrorDetails();
    if (null != basicProperty) {
        final String assessmentNo = basicProperty.getUpicNo();
        if (!basicProperty.isActive()) {
            errorDetails.setErrorCode(PROPERTY_DEACTIVATE_ERR_CODE);
            errorDetails.setErrorMessage(PROPERTY_DEACTIVATE_ERR_MSG);
            propertyTaxDetails.setErrorDetails(errorDetails);
        } else {// w  w  w.j av a  2  s  .  c  o  m
            final Set<PropertyStatusValues> statusValues = basicProperty.getPropertyStatusValuesSet();
            if (null != statusValues && !statusValues.isEmpty())
                for (final PropertyStatusValues statusValue : statusValues)
                    if (statusValue.getPropertyStatus().getStatusCode() == MARK_DEACTIVE) {
                        errorDetails.setErrorCode(PROPERTY_MARK_DEACTIVATE_ERR_CODE);
                        errorDetails.setErrorMessage(PROPERTY_MARK_DEACTIVATE_ERR_MSG);
                    }
        }
        final Property property = basicProperty.getProperty();
        ptDemandDAO.getDemandCollMap(property);

        if (!StringUtils.isBlank(category)) {
            String propType = property.getPropertyDetail().getPropertyTypeMaster().getCode();
            if (CATEGORY_TYPE_PROPERTY_TAX.equals(category)) {
                if (propType.equals(OWNERSHIP_TYPE_VAC_LAND)) {
                    errorDetails.setErrorCode(THIRD_PARTY_ERR_CODE_PROPERTY_TAX_ASSESSMENT_NOT_FOUND);
                    errorDetails.setErrorMessage(THIRD_PARTY_ERR_MSG_PROPERTY_TAX_ASSESSMENT_NOT_FOUND);
                    propertyTaxDetails.setErrorDetails(errorDetails);
                    return propertyTaxDetails;
                }
            } else if (CATEGORY_TYPE_VACANTLAND_TAX.equals(category)) {
                if (!propType.equals(OWNERSHIP_TYPE_VAC_LAND)) {
                    errorDetails.setErrorCode(THIRD_PARTY_ERR_CODE_VACANTLAND_ASSESSMENT_NOT_FOUND);
                    errorDetails.setErrorMessage(THIRD_PARTY_ERR_MSG_VACANTLAND_ASSESSMENT_NOT_FOUND);
                    propertyTaxDetails.setErrorDetails(errorDetails);
                    return propertyTaxDetails;
                }
            } else {
                errorDetails.setErrorCode(THIRD_PARTY_ERR_CODE_WRONG_CATEGORY);
                errorDetails.setErrorMessage(THIRD_PARTY_ERR_MSG_WRONG_CATEGORY);
                propertyTaxDetails.setErrorDetails(errorDetails);
                return propertyTaxDetails;
            }
        }
        final List<PropertyOwnerInfo> propOwnerInfos = property.getBasicProperty().getPropertyOwnerInfo();
        propertyTaxDetails.setOwnerDetails(new ArrayList<OwnerDetails>(0));
        OwnerDetails ow;
        for (int i = 0; i < propOwnerInfos.size(); i++) {
            final PropertyOwnerInfo propOwnerInfo = propOwnerInfos.get(i);
            final String ownerName = propOwnerInfo.getOwner().getName();
            if (null != ownerName && ownerName.trim().length() != 0) {
                ow = new OwnerDetails();
                ow.setOwnerName(ownerName);
                ow.setMobileNo(propOwnerInfo.getOwner().getMobileNumber());
                propertyTaxDetails.getOwnerDetails().add(ow);
            }
        }
        propertyTaxDetails.setPropertyAddress(property.getBasicProperty().getAddress().toString());
        propertyTaxDetails.setAssessmentNo(property.getBasicProperty().getUpicNo());
        propertyTaxDetails.setOldAssessmentNo(property.getBasicProperty().getOldMuncipalNum());
        propertyTaxDetails.setLocalityName(property.getBasicProperty().getPropertyID().getLocality().getName());

        propertyTaxBillable.setBasicProperty(basicProperty);
        propertyTaxBillable.setLevyPenalty(Boolean.TRUE);
        Map<Installment, PenaltyAndRebate> calculatedPenalty = propertyTaxBillable.getCalculatedPenalty();

        final List<Object> list = ptDemandDAO.getPropertyTaxDetails(assessmentNo);
        if (!list.isEmpty())
            propertyTaxDetails.setTaxDetails(new ArrayList<RestPropertyTaxDetails>(0));
        else {
            return propertyTaxDetails;
        }
        String loopInstallment = "";
        RestPropertyTaxDetails arrearDetails = null;
        BigDecimal total = BigDecimal.ZERO;
        for (final Object record : list) {

            final Object[] data = (Object[]) record;
            final String taxType = (String) data[0];

            final String installment = (String) data[1];
            final Double dmd = (Double) data[2];
            final Double col = (Double) data[3];
            final BigDecimal demand = BigDecimal.valueOf(dmd.doubleValue());
            final BigDecimal collection = BigDecimal.valueOf(col.doubleValue());
            if (loopInstallment.isEmpty()) {
                loopInstallment = installment;
                arrearDetails = new RestPropertyTaxDetails();
                arrearDetails.setInstallment(installment);
            }
            if (loopInstallment.equals(installment)) {

                if (DEMANDRSN_CODE_PENALTY_FINES.equalsIgnoreCase(taxType))
                    arrearDetails.setPenalty(demand.subtract(collection));
                else if (DEMANDRSN_CODE_CHQ_BOUNCE_PENALTY.equalsIgnoreCase(taxType))
                    arrearDetails.setChqBouncePenalty(demand.subtract(collection));
                else
                    total = total.add(demand.subtract(collection));

            } else {
                arrearDetails.setTaxAmount(total);
                arrearDetails.setTotalAmount(total.add(arrearDetails.getChqBouncePenalty()));
                propertyTaxDetails.getTaxDetails().add(arrearDetails);
                loopInstallment = installment;
                arrearDetails = new RestPropertyTaxDetails();
                arrearDetails.setInstallment(installment);
                total = BigDecimal.ZERO;
                if (DEMANDRSN_CODE_PENALTY_FINES.equalsIgnoreCase(taxType))
                    arrearDetails.setPenalty(demand.subtract(collection));
                else if (DEMANDRSN_CODE_CHQ_BOUNCE_PENALTY.equalsIgnoreCase(taxType))
                    arrearDetails.setChqBouncePenalty(demand.subtract(collection));
                else
                    total = total.add(demand.subtract(collection));

            }
        }
        if (arrearDetails != null) {
            arrearDetails.setTaxAmount(total);
            arrearDetails.setTotalAmount(total.add(arrearDetails.getChqBouncePenalty()));
            propertyTaxDetails.getTaxDetails().add(arrearDetails);
        }

        Set<Installment> keySet = calculatedPenalty.keySet();

        // for all years data
        for (RestPropertyTaxDetails details : propertyTaxDetails.getTaxDetails()) {
            // loop trough the penalty
            for (Installment inst : keySet) {
                if (inst.getDescription().equalsIgnoreCase(details.getInstallment())) {
                    details.setPenalty(calculatedPenalty.get(inst).getPenalty());
                    details.setRebate(calculatedPenalty.get(inst).getRebate());
                    details.setTotalAmount(
                            details.getTotalAmount().add(calculatedPenalty.get(inst).getPenalty()));
                    if (details.getRebate() != null) {
                        details.setTotalAmount(details.getTotalAmount().subtract(details.getRebate()));
                    }
                    break;
                }
            }

        }
    }

    return propertyTaxDetails;
}

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

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

    if (DECIMALS == -1 || ROUNDING == -1) {
        return ServiceUtil.returnError(
                UtilProperties.getMessage(resource, "AccountingAritmeticPropertiesNotConfigured", locale));
    }/*from   w  ww. j av  a 2s.  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 orderSubTotal = orh.getOrderItemsSubTotal();

        // these variables are for pro-rating order amounts across invoices, so they should not be rounded off for maximum accuracy
        BigDecimal invoiceShipProRateAmount = 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 = FastMap.newInstance();
            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 = FastMap.newInstance();
        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 = orderItem.getBigDecimal("unitPrice").setScale(invoiceTypeDecimals,
                    ROUNDING);

            Map<String, Object> createInvoiceItemContext = FastMap.newInstance();
            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("uomId", "");
            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);
            }

            // 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 = FastMap.newInstance();
            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())) {
                List<GenericValue> shipmentItemBillings = EntityQuery.use(delegator).from("ShipmentItemBilling")
                        .where("shipmentId", currentValue.get("shipmentId"), "shipmentItemSeqId",
                                currentValue.get("shipmentItemSeqId"))
                        .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 the absolute invoiced amount >= the abs of the adjustment amount, the full amount has already been invoiced,
                //  so skip this adjustment
                if (adj.get("amount") == null) { // JLR 17/4/7 : 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;
                }
                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) {
                        // pro-rate the amount
                        // set decimals = 100 means we don't round this intermediate value, which is very important
                        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 = FastMap.newInstance();
                    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("uomId", "");
                    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 = FastMap.newInstance();
                    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 = FastMap.newInstance();
        Map<GenericValue, BigDecimal> taxAdjustments = FastMap.newInstance();

        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 the absolute invoiced amount >= the abs of the adjustment amount, the full amount has already been invoiced,
            //  so skip this adjustment
            if (null == adj.get("amount")) { // JLR 17/4/7 : 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 (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
                calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, orderSubTotal,
                        invoiceSubTotal, 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;

                // 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 = FastList.newInstance();
        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 = FastMap.newInstance();
                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.ibm.soatf.component.soap.builder.SampleXmlUtil.java

private String formatDecimal(String start, SchemaType sType) {
    BigDecimal result = new BigDecimal(start);
    XmlDecimal xmlD;// w  w  w  . j a  va2s . com
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
    BigDecimal min = xmlD != null ? xmlD.getBigDecimalValue() : null;
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
    BigDecimal max = xmlD != null ? xmlD.getBigDecimalValue() : null;
    boolean minInclusive = true, maxInclusive = true;
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
    if (xmlD != null) {
        BigDecimal minExcl = xmlD.getBigDecimalValue();
        if (min == null || min.compareTo(minExcl) < 0) {
            min = minExcl;
            minInclusive = false;
        }
    }
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
    if (xmlD != null) {
        BigDecimal maxExcl = xmlD.getBigDecimalValue();
        if (max == null || max.compareTo(maxExcl) > 0) {
            max = maxExcl;
            maxInclusive = false;
        }
    }
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_TOTAL_DIGITS);
    int totalDigits = -1;
    if (xmlD != null) {
        totalDigits = xmlD.getBigDecimalValue().intValue();

        StringBuilder sb = new StringBuilder(totalDigits);
        for (int i = 0; i < totalDigits; i++)
            sb.append('9');
        BigDecimal digitsLimit = new BigDecimal(sb.toString());
        if (max != null && max.compareTo(digitsLimit) > 0) {
            max = digitsLimit;
            maxInclusive = true;
        }
        digitsLimit = digitsLimit.negate();
        if (min != null && min.compareTo(digitsLimit) < 0) {
            min = digitsLimit;
            minInclusive = true;
        }
    }

    int sigMin = min == null ? 1 : result.compareTo(min);
    int sigMax = max == null ? -1 : result.compareTo(max);
    boolean minOk = sigMin > 0 || sigMin == 0 && minInclusive;
    boolean maxOk = sigMax < 0 || sigMax == 0 && maxInclusive;

    // Compute the minimum increment
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_FRACTION_DIGITS);
    int fractionDigits = -1;
    BigDecimal increment;
    if (xmlD == null)
        increment = new BigDecimal(1);
    else {
        fractionDigits = xmlD.getBigDecimalValue().intValue();
        if (fractionDigits > 0) {
            StringBuilder sb = new StringBuilder("0.");
            for (int i = 1; i < fractionDigits; i++)
                sb.append('0');
            sb.append('1');
            increment = new BigDecimal(sb.toString());
        } else
            increment = new BigDecimal(1);
    }

    if (minOk && maxOk) {
        // OK
    } else if (minOk && !maxOk) {
        // TOO BIG
        if (maxInclusive)
            result = max;
        else
            result = max.subtract(increment);
    } else if (!minOk && maxOk) {
        // TOO SMALL
        if (minInclusive)
            result = min;
        else
            result = min.add(increment);
    } else {
        // MIN > MAX!!
    }

    // We have the number
    // Adjust the scale according to the totalDigits and fractionDigits
    int digits = 0;
    BigDecimal ONE = new BigDecimal(BigInteger.ONE);
    for (BigDecimal n = result; n.abs().compareTo(ONE) >= 0; digits++)
        n = n.movePointLeft(1);

    if (fractionDigits > 0)
        if (totalDigits >= 0)
            result.setScale(Math.max(fractionDigits, totalDigits - digits));
        else
            result.setScale(fractionDigits);
    else if (fractionDigits == 0)
        result.setScale(0);

    return result.toString();
}

From source file:com.centeractive.ws.builder.soap.SampleXmlUtil.java

private String formatDecimal(String start, SchemaType sType) {
    BigDecimal result = new BigDecimal(start);
    XmlDecimal xmlD;/*from   w w  w . j av  a  2 s. c o m*/
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
    BigDecimal min = xmlD != null ? xmlD.getBigDecimalValue() : null;
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
    BigDecimal max = xmlD != null ? xmlD.getBigDecimalValue() : null;
    boolean minInclusive = true, maxInclusive = true;
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
    if (xmlD != null) {
        BigDecimal minExcl = xmlD.getBigDecimalValue();
        if (min == null || min.compareTo(minExcl) < 0) {
            min = minExcl;
            minInclusive = false;
        }
    }
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
    if (xmlD != null) {
        BigDecimal maxExcl = xmlD.getBigDecimalValue();
        if (max == null || max.compareTo(maxExcl) > 0) {
            max = maxExcl;
            maxInclusive = false;
        }
    }
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_TOTAL_DIGITS);
    int totalDigits = -1;
    if (xmlD != null) {
        totalDigits = xmlD.getBigDecimalValue().intValue();

        StringBuffer sb = new StringBuffer(totalDigits);
        for (int i = 0; i < totalDigits; i++)
            sb.append('9');
        BigDecimal digitsLimit = new BigDecimal(sb.toString());
        if (max != null && max.compareTo(digitsLimit) > 0) {
            max = digitsLimit;
            maxInclusive = true;
        }
        digitsLimit = digitsLimit.negate();
        if (min != null && min.compareTo(digitsLimit) < 0) {
            min = digitsLimit;
            minInclusive = true;
        }
    }

    int sigMin = min == null ? 1 : result.compareTo(min);
    int sigMax = max == null ? -1 : result.compareTo(max);
    boolean minOk = sigMin > 0 || sigMin == 0 && minInclusive;
    boolean maxOk = sigMax < 0 || sigMax == 0 && maxInclusive;

    // Compute the minimum increment
    xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_FRACTION_DIGITS);
    int fractionDigits = -1;
    BigDecimal increment;
    if (xmlD == null)
        increment = new BigDecimal(1);
    else {
        fractionDigits = xmlD.getBigDecimalValue().intValue();
        if (fractionDigits > 0) {
            StringBuffer sb = new StringBuffer("0.");
            for (int i = 1; i < fractionDigits; i++)
                sb.append('0');
            sb.append('1');
            increment = new BigDecimal(sb.toString());
        } else
            increment = new BigDecimal(1);
    }

    if (minOk && maxOk) {
        // OK
    } else if (minOk && !maxOk) {
        // TOO BIG
        if (maxInclusive)
            result = max;
        else
            result = max.subtract(increment);
    } else if (!minOk && maxOk) {
        // TOO SMALL
        if (minInclusive)
            result = min;
        else
            result = min.add(increment);
    } else {
        // MIN > MAX!!
    }

    // We have the number
    // Adjust the scale according to the totalDigits and fractionDigits
    int digits = 0;
    BigDecimal ONE = new BigDecimal(BigInteger.ONE);
    for (BigDecimal n = result; n.abs().compareTo(ONE) >= 0; digits++)
        n = n.movePointLeft(1);

    if (fractionDigits > 0)
        if (totalDigits >= 0)
            result.setScale(Math.max(fractionDigits, totalDigits - digits));
        else
            result.setScale(fractionDigits);
    else if (fractionDigits == 0)
        result.setScale(0);

    return result.toString();
}

From source file:org.kuali.kpme.tklm.time.rules.overtime.weekly.service.WeeklyOvertimeRuleServiceImpl.java

/**
 * Applies overtime additions to the indicated TimeBlock.
 *
 * @param timeBlock The time block to apply the overtime on.
 * @param overtimeEarnCode The overtime earn code to apply overtime to.
 * @param convertFromEarnCodes The other earn codes on the time block.
 * @param overtimeHours The overtime hours to apply.
 *
 * @return the amount of overtime hours remaining to be applied.
 *///w ww . j  a  v  a 2 s.c o  m
protected BigDecimal applyPositiveOvertimeOnTimeBlock(TimeBlockBo timeBlock, String overtimeEarnCode,
        Set<String> convertFromEarnCodes, BigDecimal overtimeHours) {
    BigDecimal applied = BigDecimal.ZERO;
    List<TimeHourDetailBo> timeHourDetails = timeBlock.getTimeHourDetails();
    List<TimeHourDetailBo> newTimeHourDetails = new ArrayList<TimeHourDetailBo>();

    LOG.info("INITIAL block; " + timeBlock.getTkTimeBlockId() + "overtimeHours = " + overtimeHours
            + " overall timeblock hours = " + timeBlock.getHours() + " earnCode = " + timeBlock.getEarnCode()
            + " OT = " + overtimeEarnCode + " convertFrom = " + convertFromEarnCodes + " startDate = "
            + timeBlock.getBeginDateTime());
    for (TimeHourDetailBo timeHourDetail : timeHourDetails) {
        LOG.info("EC = " + timeHourDetail.getEarnCode() + " hours = " + timeHourDetail.getHours());
    }

    EarnCodeContract earnCodeObj = HrServiceLocator.getEarnCodeService().getEarnCode(overtimeEarnCode,
            timeBlock.getEndDateTime().toLocalDate());

    BigDecimal toApply = BigDecimal.ZERO;
    toApply = toApply.add(timeBlock.getHours());

    BigDecimal otApplied = BigDecimal.ZERO;

    BigDecimal newOtActual = BigDecimal.ZERO;

    BigDecimal maxOtToConvert = BigDecimal.ZERO;
    BigDecimal existingOtActualHours = BigDecimal.ZERO;
    BigDecimal newOt = BigDecimal.ZERO;

    TimeHourDetailBo overtimeTimeHourDetail = null;

    List<TimeHourDetailBo> toConvert = new ArrayList<TimeHourDetailBo>();

    BigDecimal regularHours = BigDecimal.ZERO;
    for (TimeHourDetailBo timeHourDetail : timeHourDetails) {
        if (convertFromEarnCodes.contains(timeHourDetail.getEarnCode())) {
            maxOtToConvert = maxOtToConvert.add(timeHourDetail.getHours());
            toConvert.add(timeHourDetail);
            regularHours = regularHours.add(timeHourDetail.getHours());
        } else if (timeHourDetail.getEarnCode().equals(overtimeEarnCode)) {
            overtimeTimeHourDetail = timeHourDetail;
        } else {
            regularHours = regularHours.add(timeHourDetail.getHours());
        }
    }

    LOG.info("regularHours = " + regularHours + " maxOtToConvert = " + maxOtToConvert + " overtimeHours = "
            + overtimeHours);

    //this is the actual hours of overtime worked before any multiplying factor.
    existingOtActualHours = timeBlock.getHours().subtract(regularHours);

    LOG.info("actual OT Hours =  " + existingOtActualHours);
    if (overtimeHours.compareTo(BigDecimal.ZERO) <= 0) {
        /*
                    if (existingOtActualHours.compareTo(BigDecimal.ZERO) == 0) {
        return  BigDecimal.ZERO;
                    }
                    else
                    {
                    */
        LOG.info("actual OT hours neq zero");

        if (existingOtActualHours.compareTo(BigDecimal.ZERO) != 0) {
            //handle this case Friday morning
            if (toConvert.size() > 0) {
                toConvert.get(0).setHours(toConvert.get(0).getHours().add(existingOtActualHours));
            } else {
                TimeHourDetailBo newTimeHourDetail = new TimeHourDetailBo();
                newTimeHourDetail.setTkTimeBlockId(timeBlock.getTkTimeBlockId());
                newTimeHourDetail.setEarnCode(convertFromEarnCodes.iterator().next());
                newTimeHourDetail.setHours(existingOtActualHours);
                timeBlock.addTimeHourDetail(newTimeHourDetail);

                //Friday
                //timeHourDetails.get(0).setHours(existingOtActualHours);
            }
        }
        newOtActual = BigDecimal.ZERO; //could this be a problem??
        newOt = BigDecimal.ZERO;
    } else if (overtimeHours.compareTo(existingOtActualHours) <= 0) // new overtime is less than old overtime
    {
        //subtract from existing OT until existing OT is zero, if necessary add to toConvert List until the difference is ZERO
        //newOtToAdd = existingOt
        BigDecimal newOtToRemove = existingOtActualHours.subtract(overtimeHours);

        newOtActual = overtimeHours;
        newOt = earnCodeObj.getInflateFactor().multiply(overtimeHours, HrConstants.MATH_CONTEXT)
                .setScale(HrConstants.BIG_DECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);

        if (toConvert.size() > 0) {
            toConvert.get(0).setHours(toConvert.get(0).getHours().add(newOtToRemove));
        } else {
            //                LOG.debug("hitting problem case");
            //                timeHourDetails.get(0).setHours(timeHourDetails.get(0).getHours().add(newOtToRemove));

            TimeHourDetailBo newTimeHourDetail = new TimeHourDetailBo();
            newTimeHourDetail.setTkTimeBlockId(timeBlock.getTkTimeBlockId());
            //                newTimeHourDetail.setEarnCode(timeBlock.getEarnCode());
            newTimeHourDetail.setEarnCode(convertFromEarnCodes.iterator().next());
            newTimeHourDetail.setHours(newOtToRemove);
            timeBlock.addTimeHourDetail(newTimeHourDetail);
        }

        LOG.info("overtimeHours <= existingOtActualHours: " + overtimeHours + " vs " + existingOtActualHours
                + "newOtActual = " + newOtActual + " newOt = " + newOt);
    } else if (overtimeHours.compareTo(existingOtActualHours) > 0) //new overtime is greater than old overtime
    {
        //add difference to OT, up to maxOtToConvert.  remove from toConvert as necessary
        BigDecimal newOtToAdd = overtimeHours.subtract(existingOtActualHours);
        BigDecimal toReduce = newOtToAdd;
        if (newOtToAdd.compareTo(maxOtToConvert) >= 0) {
            newOtToAdd = maxOtToConvert;
        }

        LOG.info("newOtToAdd: " + newOtToAdd);

        for (TimeHourDetailBo timeHourDetailBo : toConvert) {
            BigDecimal existingHours = timeHourDetailBo.getHours();
            if (toReduce.compareTo(existingHours) >= 0) {
                timeHourDetailBo.setHours(BigDecimal.ZERO);
                toReduce = toReduce.subtract(existingHours);
            } else if (toReduce.compareTo(BigDecimal.ZERO) > 0) {
                timeHourDetailBo.setHours(timeHourDetailBo.getHours().subtract(toReduce));
                toReduce = toReduce.subtract(toReduce);
            }
        }

        newOtActual = existingOtActualHours.add(newOtToAdd);
        newOt = earnCodeObj.getInflateFactor().multiply(newOtActual, HrConstants.MATH_CONTEXT)
                .setScale(HrConstants.BIG_DECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);

        LOG.info("overtimeHours > existingOtActualHours: " + overtimeHours + " vs " + existingOtActualHours
                + "newOtActual = " + newOtActual + " newOt = " + newOt);
    }

    if (overtimeTimeHourDetail != null) {
        overtimeTimeHourDetail.setHours(newOt);
    } else {
        TimeHourDetailBo newTimeHourDetail = new TimeHourDetailBo();
        newTimeHourDetail.setTkTimeBlockId(timeBlock.getTkTimeBlockId());
        newTimeHourDetail.setEarnCode(overtimeEarnCode);
        newTimeHourDetail.setHours(newOt);
        timeBlock.addTimeHourDetail(newTimeHourDetail);
    }

    LOG.info("COMPLETE block; " + timeBlock.getTkTimeBlockId() + " overall timeblock hours = "
            + timeBlock.getHours() + " earnCode = " + timeBlock.getEarnCode() + " OT = " + overtimeEarnCode
            + " convertFrom = " + convertFromEarnCodes);
    for (TimeHourDetailBo timeHourDetail : timeHourDetails) {
        LOG.info("EC = " + timeHourDetail.getEarnCode() + " hours = " + timeHourDetail.getHours());
    }

    LOG.info("returning   " + overtimeHours.subtract(newOtActual));

    return overtimeHours.subtract(newOtActual);
    /*
            if (changeMade)
            {
            }
            else
            {
    return overtimeHours;
            }
            */
}