Example usage for java.math BigDecimal multiply

List of usage examples for java.math BigDecimal multiply

Introduction

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

Prototype

public BigDecimal multiply(BigDecimal multiplicand) 

Source Link

Document

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

Usage

From source file:com.zuora.api.UsageAdjInvoiceRegenerator.java

protected UsageAdjInvoiceRegenerator() throws Exception {

    //MAX_ITEMS_PER_CALL = AppParamManager.MAX_ZOBJECTS_PER_BATCH;

    // Initialize the API Client.
    zApiClient = new ApiClient(AppParamManager.API_URL, AppParamManager.USER_NAME,
            AppParamManager.USER_PASSWORD, AppParamManager.USER_SESSION);

    zApiClient.login();//from w ww . j av  a 2  s .c om
    //Logger.print("logged in");

    /*
    threadDataArray = new ThreadData[AppParamManager.MAX_WORKING_THREADS];
            
    for (int i = 0; i < AppParamManager.MAX_WORKING_THREADS; i++) {
       threadDataArray[i] = new ThreadData(i);
    }
    */

    //int indexOfThreadDataArray = 0;
    int itemsCollectionIndex = 0;
    String savedRPId = "";
    String savedAccountId = "";
    String savedInvoiceId = "";
    String savedPRPCId = "";
    Calendar savedServiceEndDt = null;
    Calendar savedInvoiceDt = null;
    Calendar savedTargetDt = null;

    String savedBaseUOM = null;
    String savedOverUOM = null;
    String basePRPCId = null;

    List<Usage> deleteUOMs = null;

    boolean skipDelete = false;
    /*
    String InvoiceNumberDisplay = "";
    BufferedWriter  writer = new BufferedWriter(
    new FileWriter("C:\\Temp\\output"+output+".txt"));
    */

    //Logger.print("thread initiated, max objects: "+AppParamManager.MAX_ZOBJECTS_PER_BATCH+" Total number of Line Items: "+eInvoiceItemAll.size());
    //String rpcQuery1 = "SELECT Price, base_quantity__c from RatePlanCharge where ProductRatePlanChargeId = '";
    String rpcQuery1 = "SELECT Price from RatePlanCharge where ProductRatePlanChargeId = '";
    String rpcQuery2 = "' and RatePlanId = '";
    //String rpcQuery3 = "' and Base_Quantity__c <> '0'";
    String rpcQuery3 = "'";
    String finalquery = "";
    BigDecimal result = BigDecimal.ZERO;
    BigDecimal amountTotal = BigDecimal.ZERO;
    BigDecimal baseAmount = BigDecimal.ZERO;
    BigDecimal savedQuantity = BigDecimal.ZERO;

    InvoiceItemEntity baseEntity = null;
    InvoiceItemEntity overageEntity = null;

    //Logger.print("Before loop.");

    for (InvoiceItemEntity eInvoiceItem : eUsageItemsValid) {
        Logger.print("in loop0" + eInvoiceItem.getRPId());
        if (!eInvoiceItem.getRPId().equals(savedRPId)) {
            if (itemsCollectionIndex != 0) {
                Logger.print("in if 1");
                if (!skipDelete) {
                    /*
                    //add base usage
                    baseEntity = new InvoiceItemEntity();
                    baseEntity.setAccountId(savedAccountId);
                            
                    finalquery = rpcQuery1 + basePRPCId + rpcQuery2 + savedRPId + rpcQuery3;
                    results = zApiClient.getBaseQuantity(finalquery);
                    baseEntity.setQuantity(results[0]);
                    baseAmount = results[1];
                            
                    baseEntity.setUOM(savedBaseUOM);
                    baseEntity.setServiceEnddt(savedServiceEndDt);   
                    //Logger.print("setting invoice id base: "+savedInvoiceId);
                    baseEntity.setInvoiceId(savedInvoiceId);
                    baseEntity.setTargetDate(savedTargetDt);
                    baseEntity.setInvoicedate(savedInvoiceDt);
                    newUsageCollection.add(baseEntity);
                    */

                    //add overage usage
                    BigDecimal overageQnty = amountTotal.subtract(baseAmount);
                    if (overageQnty.compareTo(BigDecimal.ZERO) > 0) {
                        overageEntity = new InvoiceItemEntity();
                        overageEntity.setAccountId(savedAccountId);
                        Logger.print("setting invoice id over: " + savedInvoiceId);
                        overageEntity.setInvoiceId(savedInvoiceId);

                        overageEntity.setQuantity(overageQnty);

                        overageEntity.setUOM(savedOverUOM);
                        overageEntity.setServiceEnddt(savedServiceEndDt);
                        overageEntity.setTargetDate(savedTargetDt);
                        overageEntity.setInvoicedate(savedInvoiceDt);
                        Logger.print("added to collection, overage: " + overageEntity.getQuantity());
                        newUsageCollection.add(overageEntity);
                    }
                }

                skipDelete = false;
                amountTotal = BigDecimal.ZERO;
                baseAmount = BigDecimal.ZERO;
            }

            savedRPId = eInvoiceItem.getRPId();
            savedPRPCId = eInvoiceItem.getPRPCId();
            savedAccountId = eInvoiceItem.getAccountId();

            if (!eInvoiceItem.getInvoiceId().equals(savedInvoiceId)) {
                Logger.print("getting usage for invoice: " + eInvoiceItem.getInvoiceId());
                deleteUOMs = zApiClient.getUsageForDelete(
                        "select id, uom from usage where invoiceid = '" + eInvoiceItem.getInvoiceId() + "'");
                savedInvoiceId = eInvoiceItem.getInvoiceId();
            }
            savedInvoiceDt = eInvoiceItem.getInvoicedate();
            savedTargetDt = eInvoiceItem.getTargetDate();
            savedServiceEndDt = eInvoiceItem.getServiceEnddt();

            if (eInvoiceItem.getFeeFlag().equals("B")) {
                savedBaseUOM = eInvoiceItem.getUOM();
                basePRPCId = eInvoiceItem.getPRPCId();
            }
            if (eInvoiceItem.getFeeFlag().equals("O")) {
                savedOverUOM = eInvoiceItem.getUOM();
            }
            savedBaseUOM = null;
            savedOverUOM = null;
            savedQuantity = BigDecimal.ZERO;
        }

        Logger.print("In loop1");
        savedRPId = eInvoiceItem.getRPId();
        //Logger.print("In loop2");
        savedPRPCId = eInvoiceItem.getPRPCId();
        //Logger.print("In loop3");
        savedAccountId = eInvoiceItem.getAccountId();
        //Logger.print("In loop4");
        savedInvoiceDt = eInvoiceItem.getInvoicedate();
        //Logger.print("In loop6");
        savedTargetDt = eInvoiceItem.getTargetDate();
        //Logger.print("In loop7");
        savedServiceEndDt = eInvoiceItem.getServiceEnddt();
        //Logger.print("In loop8");

        if (eInvoiceItem.getFeeFlag().equals("B")) {
            Logger.print("setting base UOM");
            basePRPCId = eInvoiceItem.getPRPCId();

            //add base usage
            finalquery = rpcQuery1 + basePRPCId + rpcQuery2 + savedRPId + rpcQuery3;
            result = zApiClient.getBaseQuantity(finalquery);
            Logger.print("setting base UOM");
            Logger.print(
                    "curr line quantity: " + eInvoiceItem.getQuantity() + " base quantity: " + savedQuantity);
            if (result.compareTo(BigDecimal.ZERO) > 0
                    && eInvoiceItem.getQuantity().compareTo(savedQuantity) < 0) {
                //Logger.print("setting invoice id base1: ");
                savedBaseUOM = eInvoiceItem.getUOM();
                //Logger.print("setting invoice id base2: ");
                baseEntity = new InvoiceItemEntity();
                baseEntity.setAccountId(savedAccountId);
                //Logger.print("setting invoice id base3: ");
                //result
                baseEntity.setQuantity(savedQuantity);
                baseAmount = savedQuantity.multiply(result);
                baseEntity.setUOM(savedBaseUOM);
                baseEntity.setServiceEnddt(savedServiceEndDt);
                Logger.print("setting invoice id base: " + savedInvoiceId);
                baseEntity.setInvoiceId(savedInvoiceId);
                baseEntity.setTargetDate(savedTargetDt);
                baseEntity.setInvoicedate(savedInvoiceDt);
                newUsageCollection.add(baseEntity);
            }
        }

        if (eInvoiceItem.getLicenseFlag().equals("True")) {
            savedQuantity = eInvoiceItem.getQuantity();
            Logger.print("within license flag, quantity set to :" + savedQuantity);
        }

        if (eInvoiceItem.getFeeFlag().equals("O")) {
            Logger.print("setting over UOM");
            savedOverUOM = eInvoiceItem.getUOM();
        }
        if (eInvoiceItem.getFeeFlag().equals("") && eInvoiceItem.getLicenseFlag().equals("")) {
            Logger.print("setting usage " + savedBaseUOM);
            if (savedBaseUOM == null) {
                skipDelete = true;
            } else {
                Logger.print("setting usage1");
                amountTotal = amountTotal.add(eInvoiceItem.getAmount());
                Logger.print("setting usage2: " + eInvoiceItem.getInvoiceId() + " saved: " + savedInvoiceId);
                if (!eInvoiceItem.getInvoiceId().equals(savedInvoiceId)) {
                    Logger.print("setting usage3");
                    deleteUOMs = zApiClient.getUsageForDelete("select id, uom from usage where invoiceid = '"
                            + eInvoiceItem.getInvoiceId() + "'");
                    Logger.print("deleted list: " + deleteUOMs.size());
                    savedInvoiceId = eInvoiceItem.getInvoiceId();
                }
                Logger.print("before usage loop" + deleteUOMs.size());
                if (deleteUOMs.size() >= 1 && deleteUOMs.get(0).getUOM() != null) {
                    for (Usage usage : deleteUOMs) {
                        Logger.print("in loop, usage UOM: " + usage.getUOM() + " invoice UOM: "
                                + eInvoiceItem.getUOM());
                        if (usage.getUOM().equals(eInvoiceItem.getUOM())) {
                            deleteList.add(usage.getId());
                            Logger.print("added to delete list: " + usage.getUOM());
                            break;
                        }
                    }
                }
            }

        }
        itemsCollectionIndex++;
        Logger.print("done setting usage");
    }

    if (!skipDelete) {
        /*
        //add base usage
        baseEntity = new InvoiceItemEntity();
        baseEntity.setAccountId(savedAccountId);
        Logger.print("after loop1");
        finalquery = rpcQuery1 + basePRPCId + rpcQuery2 + savedRPId + rpcQuery3;
        results = zApiClient.getBaseQuantity(finalquery);
        baseEntity.setQuantity(results[0]);
        baseAmount = results[1];
        Logger.print("after loop2");
        baseEntity.setUOM(savedBaseUOM);
        baseEntity.setServiceEnddt(savedServiceEndDt);   
        Logger.print("setting invoice id base: "+savedInvoiceId);
        baseEntity.setInvoiceId(savedInvoiceId);
        baseEntity.setTargetDate(savedTargetDt);
        baseEntity.setInvoicedate(savedInvoiceDt);
        newUsageCollection.add(baseEntity);
        Logger.print("after loop3");
        //add overage usage
         */
        BigDecimal overageQnty = amountTotal.subtract(baseAmount);
        if (overageQnty.compareTo(BigDecimal.ZERO) > 0) {
            overageEntity = new InvoiceItemEntity();
            overageEntity.setAccountId(savedAccountId);
            Logger.print("after loop3.1");
            //Logger.print("setting invoice id over: "+savedInvoiceId);
            overageEntity.setInvoiceId(savedInvoiceId);
            //Logger.print("after loop3.2");

            //Logger.print("after loop3.3");
            overageEntity.setQuantity(overageQnty);
            //Logger.print("after loop4");
            overageEntity.setUOM(savedOverUOM);
            //Logger.print("after loop4.1");
            overageEntity.setServiceEnddt(savedServiceEndDt);
            //Logger.print("after loop4.2");
            overageEntity.setTargetDate(savedTargetDt);
            //Logger.print("after loop4.3");
            overageEntity.setInvoicedate(savedInvoiceDt);
            //Logger.print("after loop4.4");
            Logger.print("added to collection, overage: " + overageEntity.getQuantity());
            newUsageCollection.add(overageEntity);
            //Logger.print("after loop5");
        }
        skipDelete = false;
    }
    amountTotal = BigDecimal.ZERO;
    baseAmount = BigDecimal.ZERO;
    //writer.close();

}

From source file:org.openbravo.advpaymentmngt.process.FIN_PaymentProcess.java

private void processPayment(FIN_Payment payment, String strAction, Boolean isPosOrder, String paymentDate,
        String comingFrom, String selectedCreditLineIds) throws OBException {
    dao = new AdvPaymentMngtDao();
    String msg = "";
    try {//  w w  w .j av a2 s.co m
        final boolean isReceipt = payment.isReceipt();
        if (strAction.equals("P") || strAction.equals("D")) {
            if (payment.getBusinessPartner() != null) {
                if (FIN_Utility.isBlockedBusinessPartner(payment.getBusinessPartner().getId(), isReceipt, 4)) {
                    // If the Business Partner is blocked for Payments, the Payment will not be completed.
                    msg = OBMessageUtils.messageBD("ThebusinessPartner") + " "
                            + payment.getBusinessPartner().getIdentifier() + " "
                            + OBMessageUtils.messageBD("BusinessPartnerBlocked");
                    throw new OBException(msg);
                }
            } else {
                OBContext.setAdminMode(true);
                try {
                    for (FIN_PaymentDetail pd : payment.getFINPaymentDetailList()) {
                        for (FIN_PaymentScheduleDetail psd : pd.getFINPaymentScheduleDetailList()) {
                            BusinessPartner bPartner = null;
                            if (psd.getInvoicePaymentSchedule() != null) {
                                bPartner = psd.getInvoicePaymentSchedule().getInvoice().getBusinessPartner();
                            } else if (psd.getOrderPaymentSchedule() != null) {
                                bPartner = psd.getOrderPaymentSchedule().getOrder().getBusinessPartner();
                            }
                            if (bPartner != null && FIN_Utility.isBlockedBusinessPartner(bPartner.getId(),
                                    payment.isReceipt(), 4)) {
                                // If the Business Partner is blocked for Payments, the Payment will not be
                                // completed.
                                msg = OBMessageUtils.messageBD("ThebusinessPartner") + " "
                                        + bPartner.getIdentifier() + " "
                                        + OBMessageUtils.messageBD("BusinessPartnerBlocked");
                                throw new OBException(msg);
                            }
                        }
                    }
                } finally {
                    OBContext.restorePreviousMode();
                }
            }
        }

        if (strAction.equals("P") || strAction.equals("D")) {
            // Guess if this is a refund payment
            boolean isRefund = false;
            OBContext.setAdminMode(false);
            try {
                List<FIN_PaymentDetail> paymentDetailList = payment.getFINPaymentDetailList();
                if (paymentDetailList.size() > 0) {
                    for (FIN_PaymentDetail det : paymentDetailList) {
                        if (det.isRefund()) {
                            isRefund = true;
                            break;
                        }
                    }
                }
            } finally {
                OBContext.restorePreviousMode();
            }
            if (!isRefund) {
                // Undo Used credit as it will be calculated again
                payment.setUsedCredit(BigDecimal.ZERO);
                OBDal.getInstance().save(payment);
            }

            boolean documentEnabled = getDocumentConfirmation(null, payment.getId());
            boolean periodNotAvailable = documentEnabled
                    && !FIN_Utility.isPeriodOpen(payment.getClient().getId(),
                            payment.getDocumentType().getDocumentCategory(), payment.getOrganization().getId(),
                            OBDateUtils.formatDate(payment.getPaymentDate()))
                    && FIN_Utility.periodControlOpened(FIN_Payment.TABLE_NAME, payment.getId(),
                            FIN_Payment.TABLE_NAME + "_ID", "LE");
            if (periodNotAvailable) {
                msg = OBMessageUtils.messageBD("PeriodNotAvailable");
                throw new OBException(msg);
            }
            Set<String> documentOrganizations = OBContext.getOBContext()
                    .getOrganizationStructureProvider(payment.getClient().getId())
                    .getNaturalTree(payment.getOrganization().getId());
            if (!documentOrganizations.contains(payment.getAccount().getOrganization().getId())) {
                msg = OBMessageUtils.messageBD("APRM_FinancialAccountNotInNaturalTree");
                throw new OBException(msg);
            }
            Set<String> invoiceDocNos = new TreeSet<String>();
            Set<String> orderDocNos = new TreeSet<String>();
            Set<String> glitems = new TreeSet<String>();
            BigDecimal paymentAmount = BigDecimal.ZERO;
            BigDecimal paymentWriteOfAmount = BigDecimal.ZERO;

            // FIXME: added to access the FIN_PaymentSchedule and FIN_PaymentScheduleDetail tables to be
            // removed when new security implementation is done
            OBContext.setAdminMode();
            boolean flushDone = false;
            try {
                String strRefundCredit = "";
                // update payment schedule amount
                List<FIN_PaymentDetail> paymentDetails = payment.getFINPaymentDetailList();

                // Show error message when payment has no lines
                if (paymentDetails.size() == 0) {
                    msg = OBMessageUtils.messageBD("APRM_PaymentNoLines");
                    log4j.debug(msg);
                    throw new OBException(msg, false);
                }
                for (FIN_PaymentDetail paymentDetail : paymentDetails) {
                    for (FIN_PaymentScheduleDetail paymentScheduleDetail : paymentDetail
                            .getFINPaymentScheduleDetailList()) {
                        paymentAmount = paymentAmount.add(paymentScheduleDetail.getAmount());
                        BigDecimal writeoff = paymentScheduleDetail.getWriteoffAmount();
                        if (writeoff == null)
                            writeoff = BigDecimal.ZERO;
                        paymentWriteOfAmount = paymentWriteOfAmount.add(writeoff);
                        if (paymentScheduleDetail.getInvoicePaymentSchedule() != null) {
                            final Invoice invoice = paymentScheduleDetail.getInvoicePaymentSchedule()
                                    .getInvoice();
                            invoiceDocNos
                                    .add(FIN_Utility.getDesiredDocumentNo(payment.getOrganization(), invoice));
                        }
                        if (paymentScheduleDetail.getOrderPaymentSchedule() != null) {
                            orderDocNos.add(
                                    paymentScheduleDetail.getOrderPaymentSchedule().getOrder().getDocumentNo());
                        }
                        if (paymentScheduleDetail.getInvoicePaymentSchedule() == null
                                && paymentScheduleDetail.getOrderPaymentSchedule() == null
                                && paymentScheduleDetail.getPaymentDetails().getGLItem() == null) {
                            if (paymentDetail.isRefund())
                                strRefundCredit = OBMessageUtils.messageBD("APRM_RefundAmount");
                            else {
                                strRefundCredit = OBMessageUtils.messageBD("APRM_CreditAmount");
                                payment.setGeneratedCredit(paymentDetail.getAmount());
                            }
                            strRefundCredit += ": " + paymentDetail.getAmount().toString();
                        }
                    }
                    if (paymentDetail.getGLItem() != null)
                        glitems.add(paymentDetail.getGLItem().getName());
                }
                // Set description
                if (!isPosOrder) {
                    StringBuffer description = new StringBuffer();

                    if (payment.getDescription() != null && !payment.getDescription().equals(""))
                        description.append(payment.getDescription()).append("\n");
                    if (!invoiceDocNos.isEmpty()) {
                        description.append(OBMessageUtils.messageBD("InvoiceDocumentno"));
                        description.append(": ").append(
                                invoiceDocNos.toString().substring(1, invoiceDocNos.toString().length() - 1));
                        description.append("\n");
                    }
                    if (!orderDocNos.isEmpty()) {
                        description.append(OBMessageUtils.messageBD("OrderDocumentno"));
                        description.append(": ").append(
                                orderDocNos.toString().substring(1, orderDocNos.toString().length() - 1));
                        description.append("\n");
                    }
                    if (!glitems.isEmpty()) {
                        description.append(OBMessageUtils.messageBD("APRM_GLItem"));
                        description.append(": ")
                                .append(glitems.toString().substring(1, glitems.toString().length() - 1));
                        description.append("\n");
                    }
                    if (!"".equals(strRefundCredit))
                        description.append(strRefundCredit).append("\n");

                    String truncateDescription = (description.length() > 255)
                            ? description.substring(0, 251).concat("...").toString()
                            : description.toString();
                    payment.setDescription(truncateDescription);
                }

                if (paymentAmount.compareTo(payment.getAmount()) != 0) {
                    payment.setUsedCredit(paymentAmount.subtract(payment.getAmount()));
                }
                if (payment.getUsedCredit().compareTo(BigDecimal.ZERO) != 0) {
                    updateUsedCredit(payment, selectedCreditLineIds);
                }

                payment.setWriteoffAmount(paymentWriteOfAmount);
                payment.setProcessed(true);
                payment.setAPRMProcessPayment("RE");
                if (payment.getGeneratedCredit() == null) {
                    payment.setGeneratedCredit(BigDecimal.ZERO);
                }
                if (BigDecimal.ZERO.compareTo(payment.getUsedCredit()) != 0
                        || BigDecimal.ZERO.compareTo(payment.getGeneratedCredit()) != 0) {
                    BusinessPartner businessPartner = payment.getBusinessPartner();
                    if (businessPartner == null) {
                        msg = OBMessageUtils.messageBD("APRM_CreditWithoutBPartner");
                        throw new OBException(msg);
                    }
                    String currency = null;
                    if (businessPartner.getCurrency() == null) {
                        currency = payment.getCurrency().getId();
                        businessPartner.setCurrency(payment.getCurrency());
                    } else {
                        currency = businessPartner.getCurrency().getId();
                    }
                    if (!payment.getCurrency().getId().equals(currency)) {
                        msg = String.format(OBMessageUtils.messageBD("APRM_CreditCurrency"),
                                businessPartner.getCurrency().getISOCode());
                        throw new OBException(msg);
                    }
                }
                // Execution Process
                if (!isPosOrder && dao.isAutomatedExecutionPayment(payment.getAccount(),
                        payment.getPaymentMethod(), payment.isReceipt())) {
                    try {
                        payment.setStatus("RPAE");

                        if (dao.hasNotDeferredExecutionProcess(payment.getAccount(), payment.getPaymentMethod(),
                                payment.isReceipt())) {
                            PaymentExecutionProcess executionProcess = dao.getExecutionProcess(payment);
                            if (dao.isAutomaticExecutionProcess(executionProcess)) {
                                final List<FIN_Payment> payments = new ArrayList<FIN_Payment>(1);
                                payments.add(payment);
                                FIN_ExecutePayment executePayment = new FIN_ExecutePayment();
                                executePayment.init("APP", executionProcess, payments, null,
                                        payment.getOrganization());
                                executePayment.addInternalParameter("comingFrom", comingFrom);
                                OBError result = executePayment.execute();
                                if ("Error".equals(result.getType())) {
                                    msg = OBMessageUtils.messageBD(result.getMessage());
                                } else if (!"".equals(result.getMessage())) {
                                    String execProcessMsg = OBMessageUtils.messageBD(result.getMessage());
                                    if (!"".equals(msg)) {
                                        msg += "<br>";
                                    }
                                    msg += execProcessMsg;
                                }
                            }
                        }
                    } catch (final NoExecutionProcessFoundException e) {
                        msg = OBMessageUtils.messageBD("NoExecutionProcessFound");
                        throw new OBException(msg);
                    } catch (final Exception e) {
                        msg = OBMessageUtils.messageBD("IssueOnExecutionProcess");
                        throw new OBException(msg);
                    }
                } else {
                    BusinessPartner businessPartner = payment.getBusinessPartner();
                    // When credit is used (consumed) we compensate so_creditused as this amount is already
                    // included in the payment details. Credit consumed should not affect to so_creditused
                    if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 0
                            && payment.getUsedCredit().compareTo(BigDecimal.ZERO) != 0) {
                        if (isReceipt) {
                            increaseCustomerCredit(businessPartner, payment.getUsedCredit());
                        } else {
                            decreaseCustomerCredit(businessPartner, payment.getUsedCredit());
                        }
                    }

                    for (FIN_PaymentDetail paymentDetail : payment.getFINPaymentDetailList()) {

                        List<FIN_PaymentScheduleDetail> orderPaymentScheduleDetails = new ArrayList<FIN_PaymentScheduleDetail>(
                                paymentDetail.getFINPaymentScheduleDetailList());

                        // Get payment schedule detail list ordered by amount asc.
                        // First negative if they exist and then positives
                        if (orderPaymentScheduleDetails.size() > 1) {
                            Collections.sort(orderPaymentScheduleDetails,
                                    new Comparator<FIN_PaymentScheduleDetail>() {
                                        @Override
                                        public int compare(FIN_PaymentScheduleDetail o1,
                                                FIN_PaymentScheduleDetail o2) {
                                            // TODO Auto-generated method stub
                                            return o1.getAmount().compareTo(o2.getAmount());
                                        }
                                    });
                        }

                        for (FIN_PaymentScheduleDetail paymentScheduleDetail : orderPaymentScheduleDetails) {
                            BigDecimal amount = paymentScheduleDetail.getAmount()
                                    .add(paymentScheduleDetail.getWriteoffAmount());
                            // Do not restore paid amounts if the payment is awaiting execution.
                            boolean invoicePaidAmounts = (FIN_Utility
                                    .seqnumberpaymentstatus(isReceipt ? "RPR" : "PPM")) >= (FIN_Utility
                                            .seqnumberpaymentstatus(FIN_Utility.invoicePaymentStatus(payment)));
                            paymentScheduleDetail.setInvoicePaid(false);
                            // Payment = 0 when the payment is generated by a invoice that consume credit
                            if (invoicePaidAmounts
                                    || (payment.getAmount().compareTo(new BigDecimal("0.00")) == 0)) {
                                if (paymentScheduleDetail.getInvoicePaymentSchedule() != null) {
                                    // BP SO_CreditUsed
                                    businessPartner = paymentScheduleDetail.getInvoicePaymentSchedule()
                                            .getInvoice().getBusinessPartner();

                                    // Payments update credit opposite to invoices
                                    BigDecimal paidAmount = BigDecimal.ZERO;
                                    Invoice invoiceForConversion = paymentScheduleDetail
                                            .getInvoicePaymentSchedule() != null
                                                    ? paymentScheduleDetail.getInvoicePaymentSchedule()
                                                            .getInvoice()
                                                    : null;
                                    paidAmount = BigDecimal.ZERO;
                                    String fromCurrency = payment.getCurrency().getId();
                                    if (businessPartner.getCurrency() == null) {
                                        String errorMSG = OBMessageUtils.messageBD("InitBPCurrencyLnk", false);
                                        msg = String.format(errorMSG, businessPartner.getId(),
                                                businessPartner.getName());
                                        throw new OBException(msg);
                                    }
                                    String toCurrency = businessPartner.getCurrency().getId();
                                    if (!fromCurrency.equals(toCurrency)) {
                                        BigDecimal exchangeRate = BigDecimal.ZERO;
                                        // check at invoice document level
                                        List<ConversionRateDoc> conversionRateDocumentForInvoice = getConversionRateDocumentForInvoice(
                                                invoiceForConversion);
                                        if (conversionRateDocumentForInvoice.size() > 0) {
                                            exchangeRate = conversionRateDocumentForInvoice.get(0).getRate();
                                        } else {
                                            // global
                                            exchangeRate = getConversionRate(payment.getOrganization().getId(),
                                                    fromCurrency, toCurrency,
                                                    invoiceForConversion != null
                                                            ? invoiceForConversion.getInvoiceDate()
                                                            : payment.getPaymentDate());
                                        }
                                        if (exchangeRate == BigDecimal.ZERO) {
                                            msg = OBMessageUtils.messageBD("NoCurrencyConversion");
                                            throw new OBException(msg);
                                        }
                                        paidAmount = amount.multiply(exchangeRate);
                                    } else {
                                        paidAmount = amount;
                                    }
                                    if (isReceipt) {
                                        decreaseCustomerCredit(businessPartner, paidAmount);
                                    } else {
                                        increaseCustomerCredit(businessPartner, paidAmount);
                                    }
                                    FIN_AddPayment.updatePaymentScheduleAmounts(paymentDetail,
                                            paymentScheduleDetail.getInvoicePaymentSchedule(),
                                            paymentScheduleDetail.getAmount(),
                                            paymentScheduleDetail.getWriteoffAmount());
                                    paymentScheduleDetail.setInvoicePaid(true);
                                }

                                if (paymentScheduleDetail.getOrderPaymentSchedule() != null) {
                                    FIN_AddPayment.updatePaymentScheduleAmounts(paymentDetail,
                                            paymentScheduleDetail.getOrderPaymentSchedule(),
                                            paymentScheduleDetail.getAmount(),
                                            paymentScheduleDetail.getWriteoffAmount());
                                    paymentScheduleDetail.setInvoicePaid(true);
                                }
                                // when generating credit for a BP SO_CreditUsed is also updated
                                if (paymentScheduleDetail.getInvoicePaymentSchedule() == null
                                        && paymentScheduleDetail.getOrderPaymentSchedule() == null
                                        && paymentScheduleDetail.getPaymentDetails().getGLItem() == null
                                        && !paymentDetail.isRefund()) {
                                    // BP SO_CreditUsed
                                    if (isReceipt) {
                                        decreaseCustomerCredit(businessPartner, amount);
                                    } else {
                                        increaseCustomerCredit(businessPartner, amount);
                                    }
                                }
                            }
                        }
                    }
                    payment.setStatus(isReceipt ? "RPR" : "PPM");

                    if ((strAction.equals("D") || FIN_Utility.isAutomaticDepositWithdrawn(payment))
                            && payment.getAmount().compareTo(BigDecimal.ZERO) != 0
                            && !"TRANSACTION".equals(comingFrom)) {
                        triggerAutomaticFinancialAccountTransaction(payment);
                        flushDone = true;
                    }
                }
                if (!payment.getAccount().getCurrency().equals(payment.getCurrency())
                        && getConversionRateDocument(payment).size() == 0) {
                    insertConversionRateDocument(payment);
                    flushDone = true;
                }
            } finally {
                if (!flushDone) {
                    OBDal.getInstance().flush();
                }
                OBContext.restorePreviousMode();
            }

            // ***********************
            // Reverse Payment
            // ***********************
        } else if (strAction.equals("RV")) {
            FIN_Payment reversedPayment = (FIN_Payment) DalUtil.copy(payment, false);
            OBContext.setAdminMode();
            try {
                if (BigDecimal.ZERO.compareTo(payment.getGeneratedCredit()) != 0
                        && BigDecimal.ZERO.compareTo(payment.getUsedCredit()) != 0) {
                    throw new OBException("@APRM_CreditConsumed@");
                } else if (BigDecimal.ZERO.compareTo(payment.getGeneratedCredit()) != 0
                        && BigDecimal.ZERO.compareTo(payment.getUsedCredit()) == 0) {
                    reversedPayment.setUsedCredit(payment.getGeneratedCredit());
                    reversedPayment.setGeneratedCredit(BigDecimal.ZERO);
                } else {
                    reversedPayment.setUsedCredit(BigDecimal.ZERO);
                    reversedPayment.setGeneratedCredit(BigDecimal.ZERO);
                }
                reversedPayment.setDocumentNo(
                        "*R*" + FIN_Utility.getDocumentNo(payment.getDocumentType(), "FIN_Payment"));
                reversedPayment.setPaymentDate(FIN_Utility.getDate(paymentDate));
                reversedPayment.setDescription("");
                reversedPayment.setProcessed(false);
                reversedPayment.setPosted("N");
                reversedPayment.setProcessNow(false);
                reversedPayment.setAPRMProcessPayment("P");
                reversedPayment.setStatus("RPAP");
                // Amounts
                reversedPayment.setAmount(payment.getAmount().negate());
                reversedPayment.setWriteoffAmount(payment.getWriteoffAmount().negate());
                reversedPayment.setFinancialTransactionAmount(payment.getFinancialTransactionAmount().negate());
                OBDal.getInstance().save(reversedPayment);

                List<FIN_PaymentDetail> reversedDetails = new ArrayList<FIN_PaymentDetail>();

                OBDal.getInstance().save(reversedPayment);
                List<FIN_Payment_Credit> credits = payment.getFINPaymentCreditList();

                for (FIN_PaymentDetail pd : payment.getFINPaymentDetailList()) {
                    FIN_PaymentDetail reversedPaymentDetail = (FIN_PaymentDetail) DalUtil.copy(pd, false);
                    reversedPaymentDetail.setFinPayment(reversedPayment);
                    reversedPaymentDetail.setAmount(pd.getAmount().negate());
                    reversedPaymentDetail.setWriteoffAmount(pd.getWriteoffAmount().negate());
                    if (pd.isRefund()) {
                        reversedPaymentDetail.setPrepayment(true);
                        reversedPaymentDetail.setRefund(false);
                        reversedPayment
                                .setGeneratedCredit(reversedPayment.getGeneratedCredit().add(pd.getAmount()));
                        credits = new ArrayList<FIN_Payment_Credit>();
                        OBDal.getInstance().save(reversedPayment);
                    } else if (pd.isPrepayment()
                            && pd.getFINPaymentScheduleDetailList().get(0).getOrderPaymentSchedule() == null) {
                        reversedPaymentDetail.setPrepayment(true);
                        reversedPaymentDetail.setRefund(true);
                    }
                    List<FIN_PaymentScheduleDetail> reversedSchedDetails = new ArrayList<FIN_PaymentScheduleDetail>();
                    OBDal.getInstance().save(reversedPaymentDetail);
                    // Create or update PSD of orders and invoices to set the new outstanding amount
                    for (FIN_PaymentScheduleDetail psd : pd.getFINPaymentScheduleDetailList()) {
                        if (psd.getInvoicePaymentSchedule() != null || psd.getOrderPaymentSchedule() != null) {
                            OBCriteria<FIN_PaymentScheduleDetail> unpaidSchedDet = OBDal.getInstance()
                                    .createCriteria(FIN_PaymentScheduleDetail.class);
                            if (psd.getInvoicePaymentSchedule() != null)
                                unpaidSchedDet.add(Restrictions.eq(
                                        FIN_PaymentScheduleDetail.PROPERTY_INVOICEPAYMENTSCHEDULE,
                                        psd.getInvoicePaymentSchedule()));
                            if (psd.getOrderPaymentSchedule() != null)
                                unpaidSchedDet.add(
                                        Restrictions.eq(FIN_PaymentScheduleDetail.PROPERTY_ORDERPAYMENTSCHEDULE,
                                                psd.getOrderPaymentSchedule()));
                            unpaidSchedDet.add(
                                    Restrictions.isNull(FIN_PaymentScheduleDetail.PROPERTY_PAYMENTDETAILS));
                            List<FIN_PaymentScheduleDetail> openPSDs = unpaidSchedDet.list();
                            // If invoice/order not fully paid, update outstanding amount
                            if (openPSDs.size() > 0) {
                                FIN_PaymentScheduleDetail openPSD = openPSDs.get(0);
                                BigDecimal openAmount = openPSD.getAmount()
                                        .add(psd.getAmount().add(psd.getWriteoffAmount()));
                                if (openAmount.compareTo(BigDecimal.ZERO) == 0) {
                                    OBDal.getInstance().remove(openPSD);
                                } else {
                                    openPSD.setAmount(openAmount);
                                }
                            } else {
                                // If invoice is fully paid create a new schedule detail.
                                FIN_PaymentScheduleDetail openPSD = (FIN_PaymentScheduleDetail) DalUtil
                                        .copy(psd, false);
                                openPSD.setPaymentDetails(null);
                                // Amounts
                                openPSD.setWriteoffAmount(BigDecimal.ZERO);
                                openPSD.setAmount(psd.getAmount().add(psd.getWriteoffAmount()));

                                openPSD.setCanceled(false);
                                OBDal.getInstance().save(openPSD);
                            }
                        }

                        FIN_PaymentScheduleDetail reversedPaymentSchedDetail = (FIN_PaymentScheduleDetail) DalUtil
                                .copy(psd, false);
                        reversedPaymentSchedDetail.setPaymentDetails(reversedPaymentDetail);
                        // Amounts
                        reversedPaymentSchedDetail.setWriteoffAmount(psd.getWriteoffAmount().negate());
                        reversedPaymentSchedDetail.setAmount(psd.getAmount().negate());
                        OBDal.getInstance().save(reversedPaymentSchedDetail);
                        reversedSchedDetails.add(reversedPaymentSchedDetail);

                        if ((FIN_Utility.invoicePaymentStatus(reversedPayment)
                                .equals(reversedPayment.getStatus()))) {
                            reversedPaymentSchedDetail.setInvoicePaid(true);

                        } else {
                            reversedPaymentSchedDetail.setInvoicePaid(false);
                        }
                        OBDal.getInstance().save(reversedPaymentSchedDetail);

                    }

                    reversedPaymentDetail.setFINPaymentScheduleDetailList(reversedSchedDetails);
                    OBDal.getInstance().save(reversedPaymentDetail);
                    reversedDetails.add(reversedPaymentDetail);
                }
                reversedPayment.setFINPaymentDetailList(reversedDetails);
                OBDal.getInstance().save(reversedPayment);

                List<FIN_Payment_Credit> reversedCredits = new ArrayList<FIN_Payment_Credit>();
                for (FIN_Payment_Credit pc : credits) {
                    FIN_Payment_Credit reversedPaymentCredit = (FIN_Payment_Credit) DalUtil.copy(pc, false);
                    reversedPaymentCredit.setAmount(pc.getAmount().negate());
                    reversedPaymentCredit.setCreditPaymentUsed(pc.getCreditPaymentUsed());
                    pc.getCreditPaymentUsed().setUsedCredit(
                            pc.getCreditPaymentUsed().getUsedCredit().add(pc.getAmount().negate()));
                    reversedPaymentCredit.setPayment(reversedPayment);
                    OBDal.getInstance().save(pc.getCreditPaymentUsed());
                    OBDal.getInstance().save(reversedPaymentCredit);
                    reversedCredits.add(reversedPaymentCredit);
                }

                reversedPayment.setFINPaymentCreditList(reversedCredits);
                OBDal.getInstance().save(reversedPayment);

                List<ConversionRateDoc> conversions = new ArrayList<ConversionRateDoc>();
                for (ConversionRateDoc cr : payment.getCurrencyConversionRateDocList()) {
                    ConversionRateDoc reversedCR = (ConversionRateDoc) DalUtil.copy(cr, false);
                    reversedCR.setForeignAmount(cr.getForeignAmount().negate());
                    reversedCR.setPayment(reversedPayment);
                    OBDal.getInstance().save(reversedCR);
                    conversions.add(reversedCR);
                }
                reversedPayment.setCurrencyConversionRateDocList(conversions);
                OBDal.getInstance().save(reversedPayment);

                OBDal.getInstance().flush();
            } finally {
                OBContext.restorePreviousMode();
            }

            payment.setReversedPayment(reversedPayment);
            OBDal.getInstance().save(payment);
            OBDal.getInstance().flush();

            String newStrAction = "P";
            FIN_PaymentProcess fpp = WeldUtils.getInstanceFromStaticBeanManager(FIN_PaymentProcess.class);
            fpp.processPayment(reversedPayment, newStrAction, isPosOrder, paymentDate, comingFrom,
                    selectedCreditLineIds);

            return;

            // ***********************
            // Reactivate Payment
            // ***********************
        } else if (strAction.equals("R") || strAction.equals("RE")) {
            // Already Posted Document
            if ("Y".equals(payment.getPosted())) {
                msg = OBMessageUtils.messageBD("PostedDocument: " + payment.getDocumentNo());
                throw new OBException(msg);
            }
            // Reversed Payment
            if (payment.getReversedPayment() != null) {
                msg = OBMessageUtils.messageBD("APRM_PaymentReversed");
                throw new OBException(msg);
            }
            // Reverse Payment
            if (strAction.equals("RE") && FIN_Utility.isReversePayment(payment)) {
                msg = OBMessageUtils.messageBD("APRM_ReversePayment");
                throw new OBException(msg);
            }

            // Do not reactive the payment if it is tax payment
            if (payment.getFinancialMgmtTaxPaymentList().size() != 0) {
                msg = OBMessageUtils.messageBD("APRM_TaxPaymentReactivation");
                throw new OBException(msg);
            }

            // Transaction exists
            if (hasTransaction(payment)) {
                msg = OBMessageUtils.messageBD("APRM_TransactionExists");
                throw new OBException(msg);
            }
            // Payment with generated credit already used on other payments.
            if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 1
                    && payment.getUsedCredit().compareTo(BigDecimal.ZERO) == 1) {
                msg = OBMessageUtils.messageBD("APRM_PaymentGeneratedCreditIsUsed");
                throw new OBException(msg);
            }

            if (FIN_Utility.invoicePaymentStatus(payment) == null) {
                msg = String.format(OBMessageUtils.messageBD("APRM_NoPaymentMethod"),
                        payment.getPaymentMethod().getIdentifier(), payment.getDocumentNo(),
                        payment.getAccount().getName());
                throw new OBException(msg);
            }
            // Do not restore paid amounts if the payment is awaiting execution.
            boolean restorePaidAmounts = (FIN_Utility
                    .seqnumberpaymentstatus(payment.getStatus())) == (FIN_Utility
                            .seqnumberpaymentstatus(FIN_Utility.invoicePaymentStatus(payment)));
            // Initialize amounts
            payment.setProcessed(false);
            OBDal.getInstance().save(payment);
            OBDal.getInstance().flush();
            payment.setWriteoffAmount(BigDecimal.ZERO);

            payment.setDescription("");

            // if all line are deleted then update amount to zero
            if (strAction.equals("R")) {
                payment.setAmount(BigDecimal.ZERO);
            }

            payment.setStatus("RPAP");
            payment.setAPRMProcessPayment("P");
            OBDal.getInstance().save(payment);
            OBDal.getInstance().flush();

            final List<FIN_PaymentDetail> removedPD = new ArrayList<FIN_PaymentDetail>();
            List<FIN_PaymentScheduleDetail> removedPDS = new ArrayList<FIN_PaymentScheduleDetail>();
            final List<String> removedPDIds = new ArrayList<String>();
            // FIXME: added to access the FIN_PaymentSchedule and FIN_PaymentScheduleDetail tables to be
            // removed when new security implementation is done
            OBContext.setAdminMode();
            try {
                BusinessPartner businessPartner = payment.getBusinessPartner();
                BigDecimal paidAmount = BigDecimal.ZERO;
                if (!(businessPartner == null)) {
                    // When credit is used (consumed) we compensate so_creditused as this amount is already
                    // included in the payment details. Credit consumed should not affect to so_creditused
                    if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 0
                            && payment.getUsedCredit().compareTo(BigDecimal.ZERO) != 0) {
                        if (isReceipt) {
                            decreaseCustomerCredit(businessPartner, payment.getUsedCredit());
                        } else {
                            increaseCustomerCredit(businessPartner, payment.getUsedCredit());
                        }
                    }
                }
                List<FIN_PaymentDetail> paymentDetails = payment.getFINPaymentDetailList();
                List<ConversionRateDoc> conversionRates = payment.getCurrencyConversionRateDocList();
                Set<String> invoiceDocNos = new HashSet<String>();
                // Undo Reversed payment relationship
                List<FIN_Payment> revPayments = new ArrayList<FIN_Payment>();
                for (FIN_Payment reversedPayment : payment.getFINPaymentReversedPaymentList()) {
                    reversedPayment.setReversedPayment(null);
                    OBDal.getInstance().save(reversedPayment);
                }
                payment.setFINPaymentReversedPaymentList(revPayments);
                OBDal.getInstance().save(payment);
                for (FIN_PaymentDetail paymentDetail : paymentDetails) {
                    removedPDS = new ArrayList<FIN_PaymentScheduleDetail>();
                    for (FIN_PaymentScheduleDetail paymentScheduleDetail : paymentDetail
                            .getFINPaymentScheduleDetailList()) {
                        Boolean invoicePaidold = paymentScheduleDetail.isInvoicePaid();
                        if (invoicePaidold | paymentScheduleDetail.getInvoicePaymentSchedule() == null) {
                            BigDecimal psdWriteoffAmount = paymentScheduleDetail.getWriteoffAmount();
                            BigDecimal psdAmount = paymentScheduleDetail.getAmount();
                            BigDecimal amount = psdAmount.add(psdWriteoffAmount);
                            if (paymentScheduleDetail.getInvoicePaymentSchedule() != null) {
                                // Remove invoice description related to the credit payments
                                final Invoice invoice = paymentScheduleDetail.getInvoicePaymentSchedule()
                                        .getInvoice();
                                invoiceDocNos.add(invoice.getDocumentNo());
                                final String invDesc = invoice.getDescription();
                                if (invDesc != null) {
                                    final String creditMsg = OBMessageUtils
                                            .messageBD("APRM_InvoiceDescUsedCredit");
                                    if (creditMsg != null) {
                                        StringBuffer newDesc = new StringBuffer();
                                        for (final String line : invDesc.split("\n")) {
                                            if (!line.startsWith(
                                                    creditMsg.substring(0, creditMsg.lastIndexOf("%s")))) {
                                                newDesc.append(line);
                                                if (!"".equals(line))
                                                    newDesc.append("\n");
                                            }
                                        }
                                        if (newDesc.length() > 255) {
                                            newDesc = newDesc.delete(251, newDesc.length());
                                            newDesc = newDesc.append("...\n");
                                        }
                                        invoice.setDescription(newDesc.toString());

                                    }
                                }
                                if (restorePaidAmounts) {
                                    FIN_AddPayment.updatePaymentScheduleAmounts(paymentDetail,
                                            paymentScheduleDetail.getInvoicePaymentSchedule(),
                                            psdAmount.negate(), psdWriteoffAmount.negate());
                                    paymentScheduleDetail.setInvoicePaid(false);
                                    OBDal.getInstance().save(paymentScheduleDetail);
                                    // BP SO_CreditUsed
                                    businessPartner = paymentScheduleDetail.getInvoicePaymentSchedule()
                                            .getInvoice().getBusinessPartner();
                                    Invoice invoiceForConversion = paymentScheduleDetail
                                            .getInvoicePaymentSchedule() != null
                                                    ? paymentScheduleDetail.getInvoicePaymentSchedule()
                                                            .getInvoice()
                                                    : null;
                                    paidAmount = BigDecimal.ZERO;
                                    if (!(businessPartner == null)) {
                                        final Currency fromCurrency = payment.getCurrency();
                                        if (businessPartner.getCurrency() == null) {
                                            String errorMSG = OBMessageUtils.messageBD("InitBPCurrencyLnk",
                                                    false);
                                            msg = String.format(errorMSG, businessPartner.getId(),
                                                    businessPartner.getName());
                                            throw new OBException(msg);
                                        }
                                        final Currency toCurrency = businessPartner.getCurrency();
                                        if (fromCurrency != null && toCurrency != null
                                                && !fromCurrency.getId().equals(toCurrency.getId())) {
                                            BigDecimal exchangeRate = BigDecimal.ZERO;
                                            // check at invoice document level
                                            List<ConversionRateDoc> conversionRateDocumentForInvoice = getConversionRateDocumentForInvoice(
                                                    invoiceForConversion);
                                            if (conversionRateDocumentForInvoice.size() > 0) {
                                                exchangeRate = conversionRateDocumentForInvoice.get(0)
                                                        .getRate();
                                            } else {
                                                // global
                                                exchangeRate = getConversionRate(
                                                        payment.getOrganization().getId(), fromCurrency.getId(),
                                                        toCurrency.getId(),
                                                        invoiceForConversion != null
                                                                ? invoiceForConversion.getInvoiceDate()
                                                                : payment.getPaymentDate());
                                            }
                                            if (exchangeRate == BigDecimal.ZERO) {
                                                msg = OBMessageUtils.messageBD("NoCurrencyConversion");
                                                throw new OBException(msg);
                                            }
                                            paidAmount = amount.multiply(exchangeRate);
                                        } else {
                                            paidAmount = amount;
                                        }
                                        if (isReceipt) {
                                            increaseCustomerCredit(businessPartner, paidAmount);
                                        } else {
                                            decreaseCustomerCredit(businessPartner, paidAmount);
                                        }
                                    }
                                }
                            }
                            if (paymentScheduleDetail.getOrderPaymentSchedule() != null && restorePaidAmounts) {
                                FIN_AddPayment.updatePaymentScheduleAmounts(paymentDetail,
                                        paymentScheduleDetail.getOrderPaymentSchedule(), psdAmount.negate(),
                                        psdWriteoffAmount.negate());
                            }
                            if (restorePaidAmounts) {
                                // when generating credit for a BP SO_CreditUsed is also updated
                                if (paymentScheduleDetail.getInvoicePaymentSchedule() == null
                                        && paymentScheduleDetail.getOrderPaymentSchedule() == null
                                        && paymentScheduleDetail.getPaymentDetails().getGLItem() == null
                                        && restorePaidAmounts && !paymentDetail.isRefund()) {
                                    // BP SO_CreditUsed
                                    if (isReceipt) {
                                        increaseCustomerCredit(businessPartner, amount);
                                    } else {
                                        decreaseCustomerCredit(businessPartner, amount);
                                    }
                                }
                            }
                        }

                        if (strAction.equals("R") || (strAction.equals("RE")
                                && paymentScheduleDetail.getInvoicePaymentSchedule() == null
                                && paymentScheduleDetail.getOrderPaymentSchedule() == null
                                && paymentScheduleDetail.getPaymentDetails().getGLItem() == null)) {
                            FIN_AddPayment.mergePaymentScheduleDetails(paymentScheduleDetail);
                            removedPDS.add(paymentScheduleDetail);
                        }

                    }
                    paymentDetail.getFINPaymentScheduleDetailList().removeAll(removedPDS);
                    if (strAction.equals("R")) {
                        OBDal.getInstance().getSession().refresh(paymentDetail);
                    }
                    // If there is any schedule detail with amount zero, those are deleted
                    // Besides it removes the payment proposal lines linked to the PSD when
                    // a) we are removing the PSD and
                    // b) if we are reactivating a payment (deleting lines only) and we don't come from
                    // payment proposal reactivation process
                    for (FIN_PaymentScheduleDetail psd : removedPDS) {
                        int proposalLinesRemoved = 0;
                        if (BigDecimal.ZERO.compareTo(psd.getAmount()) == 0
                                && BigDecimal.ZERO.compareTo(psd.getWriteoffAmount()) == 0) {
                            paymentDetail.getFINPaymentScheduleDetailList().remove(psd);
                            OBDal.getInstance().getSession().refresh(paymentDetail);
                            if (psd.getInvoicePaymentSchedule() != null) {
                                psd.getInvoicePaymentSchedule()
                                        .getFINPaymentScheduleDetailInvoicePaymentScheduleList().remove(psd);
                            }
                            if (psd.getOrderPaymentSchedule() != null) {
                                psd.getOrderPaymentSchedule()
                                        .getFINPaymentScheduleDetailOrderPaymentScheduleList().remove(psd);
                            }

                            // Before deleting the PSD, we must delete any payment proposal line linked to it
                            proposalLinesRemoved = removePaymentProposalLines(psd);

                            OBDal.getInstance().remove(psd);
                        }

                        // Delete any payment proposal line linked to the PSD if we are reactivating a payment
                        // (deleting lines only), we haven't removed it in a previous step and we don't come
                        // from payment proposal reactivation process
                        if (strAction.equals("R") && proposalLinesRemoved == 0
                                && !StringUtils.equals(comingFrom,
                                        FIN_PaymentProposalProcess.COMINGFROM_PAYMENTPROPOSALPROCESS)) {
                            removePaymentProposalLines(psd);
                        }
                    }
                    if (paymentDetail.getFINPaymentScheduleDetailList().size() == 0) {
                        removedPD.add(paymentDetail);
                        removedPDIds.add(paymentDetail.getId());
                    }
                    OBDal.getInstance().save(paymentDetail);
                }
                for (String pdToRm : removedPDIds) {
                    OBDal.getInstance().remove(OBDal.getInstance().get(FIN_PaymentDetail.class, pdToRm));
                }
                payment.getFINPaymentDetailList().removeAll(removedPD);
                if (strAction.equals("R")) {
                    payment.getCurrencyConversionRateDocList().removeAll(conversionRates);
                    payment.setFinancialTransactionConvertRate(BigDecimal.ZERO);
                }
                OBDal.getInstance().save(payment);

                if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 0
                        && payment.getUsedCredit().compareTo(BigDecimal.ZERO) != 0) {
                    undoUsedCredit(payment, invoiceDocNos);
                }

                List<FIN_Payment> creditPayments = new ArrayList<FIN_Payment>();
                for (final FIN_Payment_Credit pc : payment.getFINPaymentCreditList()) {
                    creditPayments.add(pc.getCreditPaymentUsed());
                }
                for (final FIN_Payment creditPayment : creditPayments) {
                    // Update Description
                    final String payDesc = creditPayment.getDescription();
                    if (payDesc != null) {
                        final String invoiceDocNoMsg = OBMessageUtils.messageBD("APRM_CreditUsedinInvoice");
                        if (invoiceDocNoMsg != null) {
                            final StringBuffer newDesc = new StringBuffer();
                            for (final String line : payDesc.split("\n")) {
                                boolean include = true;
                                if (line.startsWith(
                                        invoiceDocNoMsg.substring(0, invoiceDocNoMsg.lastIndexOf("%s")))) {
                                    for (final String docNo : invoiceDocNos) {
                                        if (line.indexOf(docNo) > 0) {
                                            include = false;
                                            break;
                                        }
                                    }
                                }
                                if (include) {
                                    newDesc.append(line);
                                    if (!"".equals(line))
                                        newDesc.append("\n");
                                }
                            }
                            // Truncate Description to keep length as 255
                            creditPayment.setDescription(
                                    newDesc.toString().length() > 255 ? newDesc.toString().substring(0, 255)
                                            : newDesc.toString());
                        }
                    }
                }

                payment.getFINPaymentCreditList().clear();
                if (payment.isReceipt() || strAction.equals("R")) {
                    payment.setGeneratedCredit(BigDecimal.ZERO);
                }
                if (strAction.equals("R")) {
                    payment.setUsedCredit(BigDecimal.ZERO);
                }
            } finally {
                OBDal.getInstance().flush();
                OBContext.restorePreviousMode();
            }

        } else if (strAction.equals("V")) {
            // Void
            OBContext.setAdminMode();
            try {
                if (payment.isProcessed()) {
                    // Already Posted Document
                    if ("Y".equals(payment.getPosted())) {
                        msg = OBMessageUtils.messageBD("PostedDocument: " + payment.getDocumentNo());
                        throw new OBException(msg);
                    }
                    // Transaction exists
                    if (hasTransaction(payment)) {
                        msg = OBMessageUtils.messageBD("APRM_TransactionExists");
                        throw new OBException(msg);
                    }
                    // Payment with generated credit already used on other payments.
                    if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 1
                            && payment.getUsedCredit().compareTo(BigDecimal.ZERO) == 1) {
                        msg = OBMessageUtils.messageBD("APRM_PaymentGeneratedCreditIsUsed");
                        throw new OBException(msg);
                    }
                    // Payment not in Awaiting Execution
                    boolean restorePaidAmounts = (FIN_Utility
                            .seqnumberpaymentstatus(payment.getStatus())) < (FIN_Utility
                                    .seqnumberpaymentstatus(FIN_Utility.invoicePaymentStatus(payment)));
                    if (!restorePaidAmounts) {
                        msg = OBMessageUtils.messageBD("APRM_PaymentNotRPAE_NotVoid");
                        throw new OBException(msg);
                    }

                    /*
                     * Void the payment
                     */
                    payment.setStatus("RPVOID");

                    /*
                     * Cancel all payment schedule details related to the payment
                     */
                    final List<FIN_PaymentScheduleDetail> removedPDS = new ArrayList<FIN_PaymentScheduleDetail>();
                    Set<String> invoiceDocNos = new HashSet<String>();
                    for (final FIN_PaymentDetail paymentDetail : payment.getFINPaymentDetailList()) {
                        for (final FIN_PaymentScheduleDetail paymentScheduleDetail : paymentDetail
                                .getFINPaymentScheduleDetailList()) {
                            Boolean invoicePaidold = paymentScheduleDetail.isInvoicePaid();
                            if (invoicePaidold | paymentScheduleDetail.getInvoicePaymentSchedule() == null) {
                                paymentScheduleDetail.setInvoicePaid(false);
                            }
                            BigDecimal outStandingAmt = BigDecimal.ZERO;

                            if (paymentScheduleDetail.getInvoicePaymentSchedule() != null) {
                                // Related to invoices
                                for (final FIN_PaymentScheduleDetail invScheDetail : paymentScheduleDetail
                                        .getInvoicePaymentSchedule()
                                        .getFINPaymentScheduleDetailInvoicePaymentScheduleList()) {
                                    if (invScheDetail.isCanceled()) {
                                        continue;
                                    }
                                    if (invScheDetail.getPaymentDetails() == null) {
                                        outStandingAmt = outStandingAmt.add(invScheDetail.getAmount())
                                                .add(invScheDetail.getWriteoffAmount());
                                        removedPDS.add(invScheDetail);
                                    } else if (invScheDetail.equals(paymentScheduleDetail)) {
                                        outStandingAmt = outStandingAmt.add(invScheDetail.getAmount())
                                                .add(invScheDetail.getWriteoffAmount());
                                        paymentScheduleDetail.setCanceled(true);
                                    }
                                    invoiceDocNos.add(paymentScheduleDetail.getInvoicePaymentSchedule()
                                            .getInvoice().getDocumentNo());
                                }
                                // Create merged Payment Schedule Detail with the pending to be paid amount
                                if (outStandingAmt.compareTo(BigDecimal.ZERO) != 0) {
                                    final FIN_PaymentScheduleDetail mergedScheduleDetail = dao
                                            .getNewPaymentScheduleDetail(payment.getOrganization(),
                                                    outStandingAmt);
                                    mergedScheduleDetail.setInvoicePaymentSchedule(
                                            paymentScheduleDetail.getInvoicePaymentSchedule());
                                    mergedScheduleDetail.setOrderPaymentSchedule(
                                            paymentScheduleDetail.getOrderPaymentSchedule());
                                    OBDal.getInstance().save(mergedScheduleDetail);
                                }
                            } else if (paymentScheduleDetail.getOrderPaymentSchedule() != null) {
                                // Related to orders
                                for (final FIN_PaymentScheduleDetail ordScheDetail : paymentScheduleDetail
                                        .getOrderPaymentSchedule()
                                        .getFINPaymentScheduleDetailOrderPaymentScheduleList()) {
                                    if (ordScheDetail.isCanceled()) {
                                        continue;
                                    }
                                    if (ordScheDetail.getPaymentDetails() == null) {
                                        outStandingAmt = outStandingAmt.add(ordScheDetail.getAmount())
                                                .add(ordScheDetail.getWriteoffAmount());
                                        removedPDS.add(ordScheDetail);
                                    } else if (ordScheDetail.equals(paymentScheduleDetail)) {
                                        outStandingAmt = outStandingAmt.add(ordScheDetail.getAmount())
                                                .add(ordScheDetail.getWriteoffAmount());
                                        paymentScheduleDetail.setCanceled(true);
                                    }
                                }
                                // Create merged Payment Schedule Detail with the pending to be paid amount
                                if (outStandingAmt.compareTo(BigDecimal.ZERO) != 0) {
                                    final FIN_PaymentScheduleDetail mergedScheduleDetail = dao
                                            .getNewPaymentScheduleDetail(payment.getOrganization(),
                                                    outStandingAmt);
                                    mergedScheduleDetail.setOrderPaymentSchedule(
                                            paymentScheduleDetail.getOrderPaymentSchedule());
                                    OBDal.getInstance().save(mergedScheduleDetail);
                                }
                            } else if (paymentDetail.getGLItem() != null) {
                                paymentScheduleDetail.setCanceled(true);
                            } else if (paymentScheduleDetail.getOrderPaymentSchedule() == null
                                    && paymentScheduleDetail.getInvoicePaymentSchedule() == null) {
                                // Credit payment
                                payment.setGeneratedCredit(payment.getGeneratedCredit()
                                        .subtract(paymentScheduleDetail.getAmount()));
                                removedPDS.add(paymentScheduleDetail);
                            }

                            OBDal.getInstance().save(payment);
                            OBDal.getInstance().flush();
                        }
                        paymentDetail.getFINPaymentScheduleDetailList().removeAll(removedPDS);
                        for (FIN_PaymentScheduleDetail removedPD : removedPDS) {
                            if (removedPD.getOrderPaymentSchedule() != null) {
                                removedPD.getOrderPaymentSchedule()
                                        .getFINPaymentScheduleDetailOrderPaymentScheduleList()
                                        .remove(removedPD);
                                OBDal.getInstance().save(removedPD.getOrderPaymentSchedule());
                            }
                            if (removedPD.getInvoicePaymentSchedule() != null) {
                                removedPD.getInvoicePaymentSchedule()
                                        .getFINPaymentScheduleDetailInvoicePaymentScheduleList()
                                        .remove(removedPD);
                                OBDal.getInstance().save(removedPD.getInvoicePaymentSchedule());
                            }
                            OBDal.getInstance().remove(removedPD);
                        }
                        OBDal.getInstance().flush();
                        removedPDS.clear();

                    }
                    if (payment.getGeneratedCredit().compareTo(BigDecimal.ZERO) == 0
                            && payment.getUsedCredit().compareTo(BigDecimal.ZERO) == 1) {
                        undoUsedCredit(payment, invoiceDocNos);
                    }
                    payment.getFINPaymentCreditList().clear();
                    payment.setUsedCredit(BigDecimal.ZERO);
                }
                OBDal.getInstance().flush();
            } finally {
                OBContext.restorePreviousMode();
            }
        }
    } catch (final Exception e) {
        log4j.error(e.getMessage());
        msg = OBMessageUtils.translateError(FIN_Utility.getExceptionMessage(e)).getMessage();
        throw new OBException(msg);
    }
}

From source file:org.efaps.esjp.accounting.transaction.Create_Base.java

/**
 * Analyse positions from ui.//from   w w w .  j  av a 2s  .c  o m
 *
 * @param _parameter Parameter as passed by the eFaps API
 * @param _transInfo the trans info
 * @param _postFix the post fix
 * @param _accountOids the account oids
 * @param _executeRels the execute rels
 * @throws EFapsException on error
 */
public void analysePositionsFromUI(final Parameter _parameter, final TransInfo _transInfo,
        final String _postFix, final String[] _accountOids, final boolean _executeRels) throws EFapsException {
    @SuppressWarnings("unchecked")
    final Map<String, String> oidMap = (Map<String, String>) _parameter.get(ParameterValues.OIDMAP4UI);

    final String[] rowKeys = InterfaceUtils.getRowKeys(_parameter, "amount_" + _postFix, "amount_Debit",
            "amount_Credit");

    final String[] accountOids = _accountOids == null ? _parameter.getParameterValues("accountLink_" + _postFix)
            : _accountOids;
    final String[] amounts = _parameter.getParameterValues("amount_" + _postFix);
    final String[] types = _parameter.getParameterValues("type_" + _postFix);
    final String[] rateCurIds = _parameter.getParameterValues("rateCurrencyLink_" + _postFix);
    final String[] acc2accOids = _parameter.getParameterValues("acc2acc_" + _postFix);
    final String[] labelLinkOids = _parameter.getParameterValues("labelLink_" + _postFix);
    final String[] docLinkOids = _parameter.getParameterValues("docLink_" + _postFix);
    final String[] remarks = _parameter.getParameterValues("remark_" + _postFix);
    final DecimalFormat formater = NumberFormatter.get().getFormatter();
    try {
        Instance inst = _parameter.getCallInstance();
        if (!inst.getType().isKindOf(CIAccounting.Period.getType())) {
            inst = new Period().evaluateCurrentPeriod(_parameter);
        }
        final Instance curInstance = new Period().getCurrency(inst).getInstance();
        if (amounts != null) {
            for (int i = 0; i < amounts.length; i++) {
                final Instance rateCurrInst = CurrencyInst.get(Long.parseLong(rateCurIds[i])).getInstance();
                final Instance accInst = Instance.get(accountOids[i]);
                final Object[] rateObj = getRateObject(_parameter, "_" + _postFix, i);
                final RateInfo rateInfo = getRateInfo4UI(_parameter, "_" + _postFix, i);

                final Type type = Type.get(Long.parseLong(types[i]));
                final boolean isDebitTrans = type.getUUID().equals(CIAccounting.TransactionPositionDebit.uuid);

                final BigDecimal rateAmount = ((BigDecimal) formater.parse(amounts[i])).setScale(2,
                        RoundingMode.HALF_UP);
                final BigDecimal amount = Currency
                        .convertToCurrency(_parameter, rateAmount, rateInfo, null, curInstance)
                        .setScale(2, RoundingMode.HALF_UP);

                final PositionInfo pos = new PositionInfo();
                _transInfo.addPosition(pos);
                pos.setType(type).setAccInst(accInst).setCurrInst(curInstance).setRateCurrInst(rateCurrInst)
                        .setRate(rateObj).setRateAmount(isDebitTrans ? rateAmount.negate() : rateAmount)
                        .setAmount(isDebitTrans ? amount.negate() : amount).setOrder(i)
                        .setRemark(remarks == null ? null : remarks[i])
                        .setInstance(Instance.get(oidMap.get(rowKeys[i])));

                if (labelLinkOids != null) {
                    final Instance labelInst = Instance.get(labelLinkOids[i]);
                    if (labelInst.isValid()) {
                        pos.setLabelInst(labelInst)
                                .setLabelRelType(_postFix.equalsIgnoreCase("Debit")
                                        ? CIAccounting.TransactionPositionDebit2LabelProject.getType()
                                        : CIAccounting.TransactionPositionCredit2LabelProject.getType());
                    }
                }

                if (docLinkOids != null) {
                    final Instance docInst = Instance.get(docLinkOids[i]);
                    if (docInst.isValid()) {
                        final DocumentInfo docInfoTmp = new DocumentInfo(docInst);
                        if (docInfoTmp.isSumsDoc()) {
                            pos.setDocInst(docInst)
                                    .setDocRelType(_postFix.equalsIgnoreCase("Debit")
                                            ? CIAccounting.TransactionPositionDebit2SalesDocument.getType()
                                            : CIAccounting.TransactionPositionCredit2SalesDocument.getType());
                        } else {
                            pos.setDocInst(docInst)
                                    .setDocRelType(_postFix.equalsIgnoreCase("Debit")
                                            ? CIAccounting.TransactionPositionDebit2PaymentDocument.getType()
                                            : CIAccounting.TransactionPositionCredit2PaymentDocument.getType());
                        }
                    }
                }
                if (_executeRels) {
                    final QueryBuilder queryBldr = new QueryBuilder(CIAccounting.Account2AccountAbstract);
                    queryBldr.addWhereAttrEqValue(CIAccounting.Account2AccountAbstract.FromAccountLink,
                            accInst);
                    final MultiPrintQuery multi = queryBldr.getPrint();
                    final SelectBuilder selAcc = SelectBuilder.get()
                            .linkto(CIAccounting.Account2AccountAbstract.ToAccountLink).instance();
                    multi.addSelect(selAcc);
                    multi.addAttribute(CIAccounting.Account2AccountAbstract.Numerator,
                            CIAccounting.Account2AccountAbstract.Denominator,
                            CIAccounting.Account2AccountAbstract.Config);
                    multi.execute();
                    int y = 1;
                    final int group = _transInfo.getNextGroup();
                    while (multi.next()) {
                        final Instance instance = multi.getCurrentInstance();
                        final PositionInfo connPos = new PositionInfo();
                        connPos.setPosType(TransPosType.CONNECTION);
                        final Collection<Accounting.Account2AccountConfig> configs = multi
                                .getAttribute(CIAccounting.Account2AccountAbstract.Config);
                        final boolean deactivatable = configs != null
                                && configs.contains(Accounting.Account2AccountConfig.DEACTIVATABLE);
                        final boolean confCheck = isDebitTrans && configs != null
                                && configs.contains(Accounting.Account2AccountConfig.APPLY4DEBIT)
                                || !isDebitTrans && configs != null
                                        && configs.contains(Accounting.Account2AccountConfig.APPLY4CREDIT);

                        // if cannot be deactivated or selected in the UserInterface
                        if (confCheck && (!deactivatable || acc2accOids != null && deactivatable
                                && Arrays.asList(acc2accOids).contains(instance.getOid()))) {
                            final BigDecimal numerator = new BigDecimal(multi
                                    .<Integer>getAttribute(CIAccounting.Account2AccountAbstract.Numerator));
                            final BigDecimal denominator = new BigDecimal(multi
                                    .<Integer>getAttribute(CIAccounting.Account2AccountAbstract.Denominator));

                            BigDecimal amount2 = amount.multiply(numerator).divide(denominator,
                                    BigDecimal.ROUND_HALF_UP);
                            BigDecimal rateAmount2 = rateAmount.multiply(numerator).divide(denominator,
                                    BigDecimal.ROUND_HALF_UP);

                            if (instance.getType().isCIType(CIAccounting.Account2AccountCosting)) {
                                connPos.setType(type);
                            } else if (instance.getType()
                                    .isCIType(CIAccounting.Account2AccountCostingInverse)) {
                                if (type.getUUID().equals(CIAccounting.TransactionPositionDebit.uuid)) {
                                    connPos.setType(CIAccounting.TransactionPositionCredit.getType());
                                } else {
                                    connPos.setType(CIAccounting.TransactionPositionDebit.getType());
                                }
                                amount2 = amount2.negate();
                            } else if (instance.getType().isCIType(CIAccounting.Account2AccountCredit)) {
                                if (isDebitTrans) {
                                    connPos.setType(CIAccounting.TransactionPositionCredit.getType());
                                } else {
                                    connPos.setType(CIAccounting.TransactionPositionDebit.getType());
                                    amount2 = amount2.negate();
                                    rateAmount2 = rateAmount2.negate();
                                }
                            } else if (instance.getType().isCIType(CIAccounting.Account2AccountDebit)) {
                                if (isDebitTrans) {
                                    connPos.setType(CIAccounting.TransactionPositionDebit.getType());
                                    amount2 = amount2.negate();
                                    rateAmount2 = rateAmount2.negate();
                                } else {
                                    connPos.setType(CIAccounting.TransactionPositionCredit.getType());
                                }
                            }
                            if (connPos.getType() == null) {
                                Create_Base.LOG.error("Missing definition");
                            } else {
                                connPos.setOrder(i).setConnOrder(y).setGroupId(group)
                                        .setAccInst(multi.<Instance>getSelect(selAcc)).setCurrInst(curInstance)
                                        .setRateCurrInst(rateCurrInst).setRate(rateObj).setAmount(amount2)
                                        .setRateAmount(rateAmount2);
                                _transInfo.addPosition(connPos);
                            }
                            y++;
                        }
                    }
                }
            }
        }
    } catch (final ParseException e) {
        throw new EFapsException(Transaction_Base.class, "insertPositions", e);
    }
}

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

/**
 * Create Facts (the accounting logic) for ARI, ARC, ARF, API, APC.
 * /*from   w  w  w  .  j a v  a  2s.co m*/
 * <pre>
 *  ARI, ARF
 *      Receivables     DR
 *      Charge                  CR
 *      TaxDue                  CR
 *      Revenue                 CR
 *  ARC
 *      Receivables             CR
 *      Charge          DR
 *      TaxDue          DR
 *      Revenue         RR
 *  API
 *      Payables                CR
 *      Charge          DR
 *      TaxCredit       DR
 *      Expense         DR
 *  APC
 *      Payables        DR
 *      Charge                  CR
 *      TaxCredit               CR
 *      Expense                 CR
 * </pre>
 * 
 * @param as
 *          accounting schema
 * @return Fact
 */
public Fact createFact(AcctSchema as, ConnectionProvider conn, Connection con, VariablesSecureApp vars)
        throws ServletException {
    // Select specific definition
    String strClassname = AcctServerData.selectTemplateDoc(conn, as.m_C_AcctSchema_ID, DocumentType);
    if (strClassname.equals(""))
        strClassname = AcctServerData.selectTemplate(conn, as.m_C_AcctSchema_ID, AD_Table_ID);
    if (!strClassname.equals("")) {
        try {
            DocInvoiceTemplate newTemplate = (DocInvoiceTemplate) Class.forName(strClassname).newInstance();
            return newTemplate.createFact(this, as, conn, con, vars);
        } catch (Exception e) {
            log4j.error("Error while creating new instance for DocInvoiceTemplate - " + e);
        }
    }
    log4jDocInvoice.debug("Starting create fact");
    // create Fact Header
    Fact fact = new Fact(this, as, Fact.POST_Actual);
    String Fact_Acct_Group_ID = SequenceIdData.getUUID();
    // Cash based accounting
    if (!as.isAccrual())
        return null;

    /** @todo Assumes TaxIncluded = N */

    // ARI, ARF, ARI_RM
    if (DocumentType.equals(AcctServer.DOCTYPE_ARInvoice) || DocumentType.equals(AcctServer.DOCTYPE_ARProForma)
            || DocumentType.equals(AcctServer.DOCTYPE_RMSalesInvoice)) {
        log4jDocInvoice.debug("Point 1");
        // Receivables DR
        if (m_payments == null || m_payments.length == 0)
            for (int i = 0; m_debt_payments != null && i < m_debt_payments.length; i++) {
                if (m_debt_payments[i].isReceipt.equals("Y"))
                    fact.createLine(m_debt_payments[i],
                            getAccountBPartner(C_BPartner_ID, as, true, m_debt_payments[i].dpStatus, conn),
                            this.C_Currency_ID,
                            getConvertedAmt(m_debt_payments[i].Amount, m_debt_payments[i].C_Currency_ID_From,
                                    this.C_Currency_ID, DateAcct, "", AD_Client_ID, AD_Org_ID, conn),
                            "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                else
                    fact.createLine(m_debt_payments[i],
                            getAccountBPartner(C_BPartner_ID, as, false, m_debt_payments[i].dpStatus, conn),
                            this.C_Currency_ID, "",
                            getConvertedAmt(m_debt_payments[i].Amount, m_debt_payments[i].C_Currency_ID_From,
                                    this.C_Currency_ID, DateAcct, "", AD_Client_ID, AD_Org_ID, conn),
                            Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
            }
        else
            for (int i = 0; m_payments != null && i < m_payments.length; i++) {
                fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, true, false, conn),
                        this.C_Currency_ID, m_payments[i].Amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                        DocumentType, conn);
                if (m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)
                        && new BigDecimal(m_payments[i].PrepaidAmount).compareTo(ZERO) != 0) {
                    fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                            this.C_Currency_ID, m_payments[i].PrepaidAmount, "", Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                } else if (!m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)) {
                    try {
                        DocInvoiceData[] prepayments = DocInvoiceData.selectPrepayments(connectionProvider,
                                m_payments[i].Line_ID);
                        for (int j = 0; j < prepayments.length; j++) {
                            BigDecimal prePaymentAmt = convertAmount(new BigDecimal(prepayments[j].prepaidamt),
                                    true, DateAcct, TABLEID_Payment, prepayments[j].finPaymentId,
                                    m_payments[i].C_Currency_ID_From, as.m_C_Currency_ID, m_payments[i], as,
                                    fact, Fact_Acct_Group_ID, nextSeqNo(SeqNo), conn);
                            fact.createLine(m_payments[i],
                                    getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                    m_payments[i].C_Currency_ID_From, prePaymentAmt.toString(), "",
                                    Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                        }
                    } catch (ServletException e) {
                        log4jDocInvoice.warn(e);
                    }
                }
            }
        if ((m_payments == null || m_payments.length == 0)
                && (m_debt_payments == null || m_debt_payments.length == 0)) {
            BigDecimal grossamt = new BigDecimal(Amounts[AMTTYPE_Gross]);
            BigDecimal prepayment = new BigDecimal(prepaymentamt);
            BigDecimal difference = grossamt.abs().subtract(prepayment.abs());
            if (!prepaymentamt.equals("0")) {
                if (grossamt.abs().compareTo(prepayment.abs()) > 0) {
                    if (IsReturn.equals("Y")) {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                this.C_Currency_ID, "", prepaymentamt, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, false, conn),
                                this.C_Currency_ID, "", difference.toString(), Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    } else {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                this.C_Currency_ID, prepaymentamt, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, false, conn),
                                this.C_Currency_ID, difference.toString(), "", Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                } else {
                    if (IsReturn.equals("Y")) {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                this.C_Currency_ID, "", prepaymentamt, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    } else {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                this.C_Currency_ID, prepaymentamt, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    }
                }
            } else {
                fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, false, conn),
                        this.C_Currency_ID, Amounts[AMTTYPE_Gross], "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                        DocumentType, conn);
            }

        }
        // Charge CR
        log4jDocInvoice.debug("The first create line");
        fact.createLine(null, getAccount(AcctServer.ACCTTYPE_Charge, as, conn), C_Currency_ID, "",
                getAmount(AcctServer.AMTTYPE_Charge), Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
        // TaxDue CR
        log4jDocInvoice.debug("m_taxes.length: " + m_taxes);
        BigDecimal grossamt = new BigDecimal(Amounts[AMTTYPE_Gross]);
        BigDecimal prepayment = new BigDecimal(prepaymentamt);

        for (int i = 0; m_taxes != null && i < m_taxes.length; i++) {
            // New docLine created to assign C_Tax_ID value to the entry
            DocLine docLine = new DocLine(DocumentType, Record_ID, "");
            docLine.m_C_Tax_ID = m_taxes[i].m_C_Tax_ID;

            BigDecimal percentageFinalAccount = CashVATUtil._100;
            final BigDecimal taxesAmountTotal = new BigDecimal(
                    StringUtils.isBlank(m_taxes[i].m_amount) ? "0" : m_taxes[i].m_amount);
            BigDecimal taxToTransAccount = BigDecimal.ZERO;
            int precission = 0;
            OBContext.setAdminMode(true);
            try {
                Currency currency = OBDal.getInstance().get(Currency.class, C_Currency_ID);
                precission = currency.getStandardPrecision().intValue();
            } finally {
                OBContext.restorePreviousMode();
            }
            if (IsReversal.equals("Y")) {
                if (isCashVAT && m_taxes[i].m_isCashVAT) {
                    if ((m_payments == null || m_payments.length == 0)
                            && (m_debt_payments == null || m_debt_payments.length == 0)
                            && (!prepaymentamt.equals("0"))) {
                        percentageFinalAccount = ((prepayment.multiply(new BigDecimal(100)))
                                .divide(grossamt.abs(), precission, RoundingMode.HALF_UP));
                        taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                C_Currency_ID);
                    } else {
                        percentageFinalAccount = CashVATUtil
                                .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                        taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                C_Currency_ID);
                    }
                    fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue_Trans, as, conn),
                            C_Currency_ID, taxToTransAccount.toString(), "", Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                }
                final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
                fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as, conn), C_Currency_ID,
                        taxToFinalAccount.toString(), "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                        conn);
            } else {
                if (isCashVAT && m_taxes[i].m_isCashVAT) {
                    if ((m_payments == null || m_payments.length == 0)
                            && (m_debt_payments == null || m_debt_payments.length == 0)
                            && (!prepaymentamt.equals("0"))) {
                        percentageFinalAccount = ((prepayment.multiply(new BigDecimal(100)))
                                .divide(grossamt.abs(), precission, RoundingMode.HALF_UP));
                        taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                C_Currency_ID);
                    } else {
                        percentageFinalAccount = CashVATUtil
                                .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                        taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                C_Currency_ID);
                    }
                    fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue_Trans, as, conn),
                            C_Currency_ID, "", taxToTransAccount.toString(), Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                }
                final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
                fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as, conn), C_Currency_ID,
                        "", taxToFinalAccount.toString(), Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                        conn);
            }
        }
        // Revenue CR
        if (p_lines != null && p_lines.length > 0) {
            for (int i = 0; i < p_lines.length; i++) {
                Account account = ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Revenue, as,
                        conn);
                if (DocumentType.equals(AcctServer.DOCTYPE_RMSalesInvoice)) {
                    Account accountReturnMaterial = ((DocLine_Invoice) p_lines[i])
                            .getAccount(ProductInfo.ACCTTYPE_P_RevenueReturn, as, conn);
                    if (accountReturnMaterial != null) {
                        account = accountReturnMaterial;
                    }
                }
                String amount = p_lines[i].getAmount();
                String amountConverted = "";
                ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Invoice, Record_ID,
                        C_Currency_ID, as.m_C_Currency_ID);
                if (conversionRateCurrentDoc != null) {
                    amountConverted = applyRate(new BigDecimal(p_lines[i].getAmount()),
                            conversionRateCurrentDoc, true).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                } else {
                    amountConverted = getConvertedAmt(p_lines[i].getAmount(), C_Currency_ID, as.m_C_Currency_ID,
                            DateAcct, "", AD_Client_ID, AD_Org_ID, conn);
                }
                if (((DocLine_Invoice) p_lines[i]).isDeferred()) {
                    amount = createAccDefRevenueFact(
                            fact, (DocLine_Invoice) p_lines[i], account, ((DocLine_Invoice) p_lines[i])
                                    .getAccount(ProductInfo.ACCTTYPE_P_DefRevenue, as, conn),
                            amountConverted, as.m_C_Currency_ID, conn);
                    if (IsReversal.equals("Y")) {
                        fact.createLine(p_lines[i], account, as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    } else {
                        fact.createLine(p_lines[i], account, as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                } else {
                    if (IsReversal.equals("Y")) {
                        fact.createLine(p_lines[i], account, this.C_Currency_ID, amount, "", Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    } else {
                        fact.createLine(p_lines[i], account, this.C_Currency_ID, "", amount, Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                }
                // If revenue has been deferred
                if (((DocLine_Invoice) p_lines[i]).isDeferred() && !amount.equals(amountConverted)) {
                    amount = new BigDecimal(amountConverted).subtract(new BigDecimal(amount)).toString();
                    if (IsReversal.equals("Y")) {
                        fact.createLine(p_lines[i],
                                ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefRevenue, as,
                                        conn),
                                as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    } else {
                        fact.createLine(p_lines[i],
                                ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefRevenue, as,
                                        conn),
                                as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    }
                }
            }
        }
        // Set Locations
        FactLine[] fLines = fact.getLines();
        for (int i = 0; i < fLines.length; i++) {
            if (fLines[i] != null) {
                fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(conn), true, conn); // from Loc
                fLines[i].setLocationFromBPartner(C_BPartner_Location_ID, false, conn); // to Loc
            }
        }
    }
    // ARC
    else if (this.DocumentType.equals(AcctServer.DOCTYPE_ARCredit)) {
        log4jDocInvoice.debug("Point 2");
        // Receivables CR
        if (m_payments == null || m_payments.length == 0)
            for (int i = 0; m_debt_payments != null && i < m_debt_payments.length; i++) {
                BigDecimal amount = new BigDecimal(m_debt_payments[i].Amount);
                // BigDecimal ZERO = BigDecimal.ZERO;
                fact.createLine(m_debt_payments[i],
                        getAccountBPartner(C_BPartner_ID, as, true, m_debt_payments[i].dpStatus, conn),
                        this.C_Currency_ID, "",
                        getConvertedAmt(((amount.negate())).toPlainString(),
                                m_debt_payments[i].C_Currency_ID_From, this.C_Currency_ID, DateAcct, "",
                                AD_Client_ID, AD_Org_ID, conn),
                        Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
            }
        else
            for (int i = 0; m_payments != null && i < m_payments.length; i++) {
                BigDecimal amount = new BigDecimal(m_payments[i].Amount);
                BigDecimal prepaidAmount = new BigDecimal(m_payments[i].PrepaidAmount);
                fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, true, false, conn),
                        this.C_Currency_ID, "", amount.negate().toString(), Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
                // Pre-payment: Probably not needed as at this point we can not generate pre-payments
                // against ARC. Amount is negated
                if (m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)
                        && prepaidAmount.compareTo(ZERO) != 0) {
                    fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                            this.C_Currency_ID, "", prepaidAmount.negate().toString(), Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                } else if (!m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)) {
                    try {
                        DocInvoiceData[] prepayments = DocInvoiceData.selectPrepayments(connectionProvider,
                                m_payments[i].Line_ID);
                        for (int j = 0; j < prepayments.length; j++) {
                            BigDecimal prePaymentAmt = convertAmount(
                                    new BigDecimal(prepayments[j].prepaidamt).negate(), true, DateAcct,
                                    TABLEID_Payment, prepayments[j].finPaymentId,
                                    m_payments[i].C_Currency_ID_From, as.m_C_Currency_ID, m_payments[i], as,
                                    fact, Fact_Acct_Group_ID, nextSeqNo(SeqNo), conn);
                            fact.createLine(m_payments[i],
                                    getAccountBPartner(C_BPartner_ID, as, true, true, conn),
                                    m_payments[i].C_Currency_ID_From, "", prePaymentAmt.toString(),
                                    Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                        }
                    } catch (ServletException e) {
                        log4jDocInvoice.warn(e);
                    }
                }
            }
        if ((m_payments == null || m_payments.length == 0)
                && (m_debt_payments == null || m_debt_payments.length == 0)) {
            fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, true, false, conn), this.C_Currency_ID,
                    "", Amounts[AMTTYPE_Gross], Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
        }
        // Charge DR
        fact.createLine(null, getAccount(AcctServer.ACCTTYPE_Charge, as, conn), this.C_Currency_ID,
                getAmount(AcctServer.AMTTYPE_Charge), "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                conn);
        // TaxDue DR
        for (int i = 0; m_taxes != null && i < m_taxes.length; i++) {
            // New docLine created to assign C_Tax_ID value to the entry
            DocLine docLine = new DocLine(DocumentType, Record_ID, "");
            docLine.m_C_Tax_ID = m_taxes[i].m_C_Tax_ID;

            BigDecimal percentageFinalAccount = CashVATUtil._100;
            final BigDecimal taxesAmountTotal = new BigDecimal(
                    StringUtils.isBlank(m_taxes[i].getAmount()) ? "0" : m_taxes[i].getAmount());
            BigDecimal taxToTransAccount = BigDecimal.ZERO;
            if (isCashVAT && m_taxes[i].m_isCashVAT) {
                percentageFinalAccount = CashVATUtil
                        .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                        CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal, C_Currency_ID);
                fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue_Trans, as, conn),
                        this.C_Currency_ID, taxToTransAccount.toString(), "", Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            }
            final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
            fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as, conn),
                    this.C_Currency_ID, taxToFinalAccount.toString(), "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                    DocumentType, conn);
        }
        // Revenue CR
        for (int i = 0; p_lines != null && i < p_lines.length; i++) {
            String amount = p_lines[i].getAmount();
            String amountCoverted = "";
            ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Invoice, Record_ID,
                    C_Currency_ID, as.m_C_Currency_ID);
            if (conversionRateCurrentDoc != null) {
                amountCoverted = applyRate(new BigDecimal(p_lines[i].getAmount()), conversionRateCurrentDoc,
                        true).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            } else {
                amountCoverted = getConvertedAmt(p_lines[i].getAmount(), C_Currency_ID, as.m_C_Currency_ID,
                        DateAcct, "", AD_Client_ID, AD_Org_ID, conn);
            }
            Account account = ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Revenue, as,
                    conn);
            if (((DocLine_Invoice) p_lines[i]).isDeferred()) {
                amount = createAccDefRevenueFact(fact, (DocLine_Invoice) p_lines[i], account,
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefRevenue, as, conn),
                        amountCoverted, as.m_C_Currency_ID, conn);
                fact.createLine(p_lines[i], account, as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            } else {
                fact.createLine(p_lines[i], account, this.C_Currency_ID, amount, "", Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            }
            // If revenue has been deferred
            if (((DocLine_Invoice) p_lines[i]).isDeferred() && !amount.equals(amountCoverted)) {
                amount = new BigDecimal(amountCoverted).subtract(new BigDecimal(amount)).toString();
                fact.createLine(p_lines[i],
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefRevenue, as, conn),
                        as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                        conn);
            }
        }
        // Set Locations
        FactLine[] fLines = fact.getLines();
        for (int i = 0; fLines != null && i < fLines.length; i++) {
            if (fLines[i] != null) {
                fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(conn), true, conn); // from Loc
                fLines[i].setLocationFromBPartner(C_BPartner_Location_ID, false, conn); // to Loc
            }
        }
    }
    // API
    else if (this.DocumentType.equals(AcctServer.DOCTYPE_APInvoice)) {
        log4jDocInvoice.debug("Point 3");
        // Liability CR
        if (m_payments == null || m_payments.length == 0)
            for (int i = 0; m_debt_payments != null && i < m_debt_payments.length; i++) {
                if (m_debt_payments[i].isReceipt.equals("Y"))
                    fact.createLine(m_debt_payments[i],
                            getAccountBPartner(C_BPartner_ID, as, true, m_debt_payments[i].dpStatus, conn),
                            this.C_Currency_ID,
                            getConvertedAmt(m_debt_payments[i].Amount, m_debt_payments[i].C_Currency_ID_From,
                                    this.C_Currency_ID, DateAcct, "", AD_Client_ID, AD_Org_ID, conn),
                            "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                else
                    fact.createLine(m_debt_payments[i],
                            getAccountBPartner(C_BPartner_ID, as, false, m_debt_payments[i].dpStatus, conn),
                            this.C_Currency_ID, "",
                            getConvertedAmt(m_debt_payments[i].Amount, m_debt_payments[i].C_Currency_ID_From,
                                    this.C_Currency_ID, DateAcct, "", AD_Client_ID, AD_Org_ID, conn),
                            Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
            }
        else
            for (int i = 0; m_payments != null && i < m_payments.length; i++) {
                fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, false, false, conn),
                        this.C_Currency_ID, "", m_payments[i].Amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                        DocumentType, conn);
                if (m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)
                        && new BigDecimal(m_payments[i].PrepaidAmount).compareTo(ZERO) != 0) {
                    fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                            this.C_Currency_ID, "", m_payments[i].PrepaidAmount, Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                } else if (!m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)) {
                    try {
                        DocInvoiceData[] prepayments = DocInvoiceData.selectPrepayments(connectionProvider,
                                m_payments[i].Line_ID);
                        for (int j = 0; j < prepayments.length; j++) {
                            BigDecimal prePaymentAmt = convertAmount(new BigDecimal(prepayments[j].prepaidamt),
                                    false, DateAcct, TABLEID_Payment, prepayments[j].finPaymentId,
                                    m_payments[i].C_Currency_ID_From, as.m_C_Currency_ID, m_payments[i], as,
                                    fact, Fact_Acct_Group_ID, nextSeqNo(SeqNo), conn);
                            fact.createLine(m_payments[i],
                                    getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                    m_payments[i].C_Currency_ID_From, "", prePaymentAmt.toString(),
                                    Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                        }
                    } catch (ServletException e) {
                        log4jDocInvoice.warn(e);
                    }
                }
            }
        if ((m_payments == null || m_payments.length == 0)
                && (m_debt_payments == null || m_debt_payments.length == 0)) {
            BigDecimal grossamt = new BigDecimal(Amounts[AMTTYPE_Gross]);
            BigDecimal prepayment = new BigDecimal(prepaymentamt);
            BigDecimal difference = grossamt.abs().subtract(prepayment.abs());
            if (!prepaymentamt.equals("0")) {
                if (grossamt.abs().compareTo(prepayment.abs()) > 0) {
                    if (IsReturn.equals("Y")) {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                this.C_Currency_ID, prepaymentamt, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, false, conn),
                                this.C_Currency_ID, difference.toString(), "", Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    } else {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                this.C_Currency_ID, "", prepaymentamt, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, false, conn),
                                this.C_Currency_ID, "", difference.toString(), Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                } else {
                    if (IsReturn.equals("Y")) {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                this.C_Currency_ID, prepaymentamt, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    } else {
                        fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                this.C_Currency_ID, "", prepaymentamt, Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                                DocumentType, conn);
                    }
                }
            } else {
                fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, false, conn),
                        this.C_Currency_ID, "", Amounts[AMTTYPE_Gross], Fact_Acct_Group_ID, nextSeqNo(SeqNo),
                        DocumentType, conn);
            }

        }
        // Charge DR
        fact.createLine(null, getAccount(AcctServer.ACCTTYPE_Charge, as, conn), this.C_Currency_ID,
                getAmount(AcctServer.AMTTYPE_Charge), "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                conn);
        BigDecimal grossamt = new BigDecimal(Amounts[AMTTYPE_Gross]);
        BigDecimal prepayment = new BigDecimal(prepaymentamt);
        // TaxCredit DR
        for (int i = 0; m_taxes != null && i < m_taxes.length; i++) {
            // New docLine created to assign C_Tax_ID value to the entry
            DocLine docLine = new DocLine(DocumentType, Record_ID, "");
            docLine.m_C_Tax_ID = m_taxes[i].m_C_Tax_ID;
            OBContext.setAdminMode(true);
            int precission = 0;
            try {
                Currency currency = OBDal.getInstance().get(Currency.class, C_Currency_ID);
                precission = currency.getStandardPrecision().intValue();
            } finally {
                OBContext.restorePreviousMode();
            }
            if (!m_taxes[i].m_isTaxUndeductable) {
                BigDecimal percentageFinalAccount = CashVATUtil._100;
                final BigDecimal taxesAmountTotal = new BigDecimal(
                        StringUtils.isBlank(m_taxes[i].getAmount()) ? "0" : m_taxes[i].getAmount());
                BigDecimal taxToTransAccount = BigDecimal.ZERO;
                if (IsReversal.equals("Y")) {
                    if (isCashVAT && m_taxes[i].m_isCashVAT) {
                        if ((m_payments == null || m_payments.length == 0)
                                && (m_debt_payments == null || m_debt_payments.length == 0)
                                && (!prepaymentamt.equals("0"))) {
                            percentageFinalAccount = ((prepayment.multiply(new BigDecimal(100)))
                                    .divide(grossamt.abs(), precission, RoundingMode.HALF_UP));
                            taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                    CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                    C_Currency_ID);
                        } else {
                            percentageFinalAccount = CashVATUtil
                                    .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                            taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                    CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                    C_Currency_ID);
                        }
                        fact.createLine(docLine,
                                m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit_Trans, as, conn),
                                this.C_Currency_ID, "", taxToTransAccount.toString(), Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                    final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
                    fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit, as, conn),
                            this.C_Currency_ID, "", taxToFinalAccount.toString(), Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                } else {
                    if (isCashVAT && m_taxes[i].m_isCashVAT) {
                        if ((m_payments == null || m_payments.length == 0)
                                && (m_debt_payments == null || m_debt_payments.length == 0)
                                && (!prepaymentamt.equals("0"))) {
                            percentageFinalAccount = ((prepayment.multiply(new BigDecimal(100)))
                                    .divide(grossamt.abs(), precission, RoundingMode.HALF_UP));
                            taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                    CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                    C_Currency_ID);
                        } else {
                            percentageFinalAccount = CashVATUtil
                                    .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                            taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                                    CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal,
                                    C_Currency_ID);
                        }
                        fact.createLine(docLine,
                                m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit_Trans, as, conn),
                                this.C_Currency_ID, taxToTransAccount.toString(), "", Fact_Acct_Group_ID,
                                nextSeqNo(SeqNo), DocumentType, conn);
                    }
                    final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
                    fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit, as, conn),
                            this.C_Currency_ID, taxToFinalAccount.toString(), "", Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                }

            } else {
                DocLineInvoiceData[] data = null;
                try {
                    data = DocLineInvoiceData.selectUndeductable(connectionProvider, Record_ID);
                } catch (ServletException e) {
                    log4jDocInvoice.warn(e);
                }

                BigDecimal cumulativeTaxLineAmount = new BigDecimal(0);
                BigDecimal taxAmount = new BigDecimal(0);
                for (int j = 0; data != null && j < data.length; j++) {
                    DocLine docLine1 = new DocLine(DocumentType, Record_ID, "");
                    docLine1.m_C_Tax_ID = data[j].cTaxId;
                    docLine1.m_C_BPartner_ID = data[j].cBpartnerId;
                    docLine1.m_M_Product_ID = data[j].mProductId;
                    docLine1.m_C_Costcenter_ID = data[j].cCostcenterId;
                    docLine1.m_C_Project_ID = data[j].cProjectId;
                    docLine1.m_User1_ID = data[j].user1id;
                    docLine1.m_User2_ID = data[j].user2id;
                    docLine1.m_C_Activity_ID = data[j].cActivityId;
                    docLine1.m_C_Campaign_ID = data[j].cCampaignId;
                    docLine1.m_A_Asset_ID = data[j].aAssetId;
                    String strtaxAmount = null;

                    try {

                        DocInvoiceData[] dataEx = DocInvoiceData.selectProductAcct(conn,
                                as.getC_AcctSchema_ID(), m_taxes[i].m_C_Tax_ID, Record_ID);
                        if (dataEx.length == 0) {
                            dataEx = DocInvoiceData.selectGLItemAcctForTaxLine(conn, as.getC_AcctSchema_ID(),
                                    m_taxes[i].m_C_Tax_ID, Record_ID);
                        }
                        strtaxAmount = m_taxes[i].getAmount();
                        taxAmount = new BigDecimal(strtaxAmount.equals("") ? "0.00" : strtaxAmount);
                        if (j == data.length - 1) {
                            data[j].taxamt = taxAmount.subtract(cumulativeTaxLineAmount).toPlainString();
                        }
                        try {

                            if (this.DocumentType.equals(AcctServer.DOCTYPE_APInvoice)) {
                                if (IsReversal.equals("Y")) {
                                    fact.createLine(docLine1, Account.getAccount(conn, dataEx[0].pExpenseAcct),
                                            this.C_Currency_ID, "", data[j].taxamt, Fact_Acct_Group_ID,
                                            nextSeqNo(SeqNo), DocumentType, conn);

                                } else {
                                    fact.createLine(docLine1, Account.getAccount(conn, dataEx[0].pExpenseAcct),
                                            this.C_Currency_ID, data[j].taxamt, "", Fact_Acct_Group_ID,
                                            nextSeqNo(SeqNo), DocumentType, conn);
                                }
                            } else if (this.DocumentType.equals(AcctServer.DOCTYPE_APCredit)) {
                                fact.createLine(docLine1, Account.getAccount(conn, dataEx[0].pExpenseAcct),
                                        this.C_Currency_ID, "", data[j].taxamt, Fact_Acct_Group_ID,
                                        nextSeqNo(SeqNo), DocumentType, conn);
                            }
                            cumulativeTaxLineAmount = cumulativeTaxLineAmount
                                    .add(new BigDecimal(data[j].taxamt));
                        } catch (ServletException e) {
                            log4jDocInvoice.error("Exception in createLineForTaxUndeductable method: " + e);
                        }
                    } catch (ServletException e) {
                        log4jDocInvoice.warn(e);
                    }
                }
            }
        }
        // Expense DR
        for (int i = 0; p_lines != null && i < p_lines.length; i++) {
            String amount = p_lines[i].getAmount();
            String amountConverted = "";
            ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Invoice, Record_ID,
                    C_Currency_ID, as.m_C_Currency_ID);
            if (conversionRateCurrentDoc != null) {
                amountConverted = applyRate(new BigDecimal(p_lines[i].getAmount()), conversionRateCurrentDoc,
                        true).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            } else {
                amountConverted = getConvertedAmt(p_lines[i].getAmount(), C_Currency_ID, as.m_C_Currency_ID,
                        DateAcct, "", AD_Client_ID, AD_Org_ID, conn);
            }
            if (((DocLine_Invoice) p_lines[i]).isDeferred()) {
                amount = createAccDefExpenseFact(fact, (DocLine_Invoice) p_lines[i],
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as, conn),
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefExpense, as, conn),
                        amountConverted, as.m_C_Currency_ID, conn);
                if (IsReversal.equals("Y")) {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as, conn),
                            as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                } else {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as, conn),
                            as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                }
            } else {
                if (IsReversal.equals("Y")) {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as, conn),
                            this.C_Currency_ID, "", amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                } else {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as, conn),
                            this.C_Currency_ID, amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                }
            }
            // If expense has been deferred
            if (((DocLine_Invoice) p_lines[i]).isDeferred() && !amount.equals(amountConverted)) {
                amount = new BigDecimal(amountConverted).subtract(new BigDecimal(amount)).toString();
                if (IsReversal.equals("Y")) {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefExpense, as,
                                    conn),
                            as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                } else {
                    fact.createLine(p_lines[i],
                            ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefExpense, as,
                                    conn),
                            as.m_C_Currency_ID, amount, "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                            conn);
                }
            }
        }
        // Set Locations
        FactLine[] fLines = fact.getLines();
        for (int i = 0; fLines != null && i < fLines.length; i++) {
            if (fLines[i] != null) {
                fLines[i].setLocationFromBPartner(C_BPartner_Location_ID, true, conn); // from Loc
                fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(conn), false, conn); // to Loc
            }
        }
        updateProductInfo(as.getC_AcctSchema_ID(), conn, con); // only API
    }
    // APC
    else if (this.DocumentType.equals(AcctServer.DOCTYPE_APCredit)) {
        log4jDocInvoice.debug("Point 4");
        // Liability DR
        if (m_payments == null || m_payments.length == 0)
            for (int i = 0; m_debt_payments != null && i < m_debt_payments.length; i++) {
                BigDecimal amount = new BigDecimal(m_debt_payments[i].Amount);
                // BigDecimal ZERO = BigDecimal.ZERO;
                fact.createLine(m_debt_payments[i],
                        getAccountBPartner(C_BPartner_ID, as, false, m_debt_payments[i].dpStatus, conn),
                        this.C_Currency_ID,
                        getConvertedAmt(((amount.negate())).toPlainString(),
                                m_debt_payments[i].C_Currency_ID_From, this.C_Currency_ID, DateAcct, "",
                                AD_Client_ID, AD_Org_ID, conn),
                        "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
            }
        else
            for (int i = 0; m_payments != null && i < m_payments.length; i++) {
                BigDecimal amount = new BigDecimal(m_payments[i].Amount);
                BigDecimal prepaidAmount = new BigDecimal(m_payments[i].PrepaidAmount);
                fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, false, false, conn),
                        this.C_Currency_ID, amount.negate().toString(), "", Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
                // Pre-payment: Probably not needed as at this point we can not generate pre-payments
                // against APC. Amount is negated
                if (m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)
                        && prepaidAmount.compareTo(ZERO) != 0) {
                    fact.createLine(m_payments[i], getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                            this.C_Currency_ID, prepaidAmount.negate().toString(), "", Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                } else if (!m_payments[i].C_Currency_ID_From.equals(as.m_C_Currency_ID)) {
                    try {
                        DocInvoiceData[] prepayments = DocInvoiceData.selectPrepayments(connectionProvider,
                                m_payments[i].Line_ID);
                        for (int j = 0; j < prepayments.length; j++) {
                            BigDecimal prePaymentAmt = convertAmount(
                                    new BigDecimal(prepayments[j].prepaidamt).negate(), false, DateAcct,
                                    TABLEID_Payment, prepayments[j].finPaymentId,
                                    m_payments[i].C_Currency_ID_From, as.m_C_Currency_ID, m_payments[i], as,
                                    fact, Fact_Acct_Group_ID, nextSeqNo(SeqNo), conn);
                            fact.createLine(m_payments[i],
                                    getAccountBPartner(C_BPartner_ID, as, false, true, conn),
                                    m_payments[i].C_Currency_ID_From, prePaymentAmt.toString(), "",
                                    Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
                        }
                    } catch (ServletException e) {
                        log4jDocInvoice.warn(e);
                    }
                }
            }
        if ((m_payments == null || m_payments.length == 0)
                && (m_debt_payments == null || m_debt_payments.length == 0)) {
            fact.createLine(null, getAccountBPartner(C_BPartner_ID, as, false, false, conn), this.C_Currency_ID,
                    Amounts[AMTTYPE_Gross], "", Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
        }
        // Charge CR
        fact.createLine(null, getAccount(AcctServer.ACCTTYPE_Charge, as, conn), this.C_Currency_ID, "",
                getAmount(AcctServer.AMTTYPE_Charge), Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType, conn);
        // TaxCredit CR
        for (int i = 0; m_taxes != null && i < m_taxes.length; i++) {
            // New docLine created to assign C_Tax_ID value to the entry
            DocLine docLine = new DocLine(DocumentType, Record_ID, "");
            docLine.m_C_Tax_ID = m_taxes[i].m_C_Tax_ID;
            if (m_taxes[i].m_isTaxUndeductable) {
                computeTaxUndeductableLine(conn, as, fact, docLine, Fact_Acct_Group_ID, m_taxes[i].m_C_Tax_ID,
                        m_taxes[i].getAmount());

            } else {
                BigDecimal percentageFinalAccount = CashVATUtil._100;
                final BigDecimal taxesAmountTotal = new BigDecimal(
                        StringUtils.isBlank(m_taxes[i].getAmount()) ? "0" : m_taxes[i].getAmount());
                BigDecimal taxToTransAccount = BigDecimal.ZERO;
                if (isCashVAT && m_taxes[i].m_isCashVAT) {
                    percentageFinalAccount = CashVATUtil
                            .calculatePrepaidPercentageForCashVATTax(m_taxes[i].m_C_Tax_ID, Record_ID);
                    taxToTransAccount = CashVATUtil.calculatePercentageAmount(
                            CashVATUtil._100.subtract(percentageFinalAccount), taxesAmountTotal, C_Currency_ID);
                    fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit_Trans, as, conn),
                            this.C_Currency_ID, "", taxToTransAccount.toString(), Fact_Acct_Group_ID,
                            nextSeqNo(SeqNo), DocumentType, conn);
                }
                final BigDecimal taxToFinalAccount = taxesAmountTotal.subtract(taxToTransAccount);
                fact.createLine(docLine, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxCredit, as, conn),
                        this.C_Currency_ID, "", taxToFinalAccount.toString(), Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            }
        }
        // Expense CR
        for (int i = 0; p_lines != null && i < p_lines.length; i++) {
            String amount = p_lines[i].getAmount();
            String amountConverted = "";
            ConversionRateDoc conversionRateCurrentDoc = getConversionRateDoc(TABLEID_Invoice, Record_ID,
                    C_Currency_ID, as.m_C_Currency_ID);
            if (conversionRateCurrentDoc != null) {
                amountConverted = applyRate(new BigDecimal(p_lines[i].getAmount()), conversionRateCurrentDoc,
                        true).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            } else {
                amountConverted = getConvertedAmt(p_lines[i].getAmount(), C_Currency_ID, as.m_C_Currency_ID,
                        DateAcct, "", AD_Client_ID, AD_Org_ID, conn);
            }
            Account account = ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Expense, as,
                    conn);
            if (((DocLine_Invoice) p_lines[i]).isDeferred()) {
                amount = createAccDefExpenseFact(fact, (DocLine_Invoice) p_lines[i], account,
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefExpense, as, conn),
                        amountConverted, as.m_C_Currency_ID, conn);
                fact.createLine(p_lines[i], account, as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            } else {
                fact.createLine(p_lines[i], account, this.C_Currency_ID, "", amount, Fact_Acct_Group_ID,
                        nextSeqNo(SeqNo), DocumentType, conn);
            }
            // If expense has been deferred
            if (((DocLine_Invoice) p_lines[i]).isDeferred() && !amount.equals(amountConverted)) {
                amount = new BigDecimal(amountConverted).subtract(new BigDecimal(amount)).toString();
                fact.createLine(p_lines[i],
                        ((DocLine_Invoice) p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_DefExpense, as, conn),
                        as.m_C_Currency_ID, "", amount, Fact_Acct_Group_ID, nextSeqNo(SeqNo), DocumentType,
                        conn);
            }

        }
        // Set Locations
        FactLine[] fLines = fact.getLines();
        for (int i = 0; fLines != null && i < fLines.length; i++) {
            if (fLines[i] != null) {
                fLines[i].setLocationFromBPartner(C_BPartner_Location_ID, true, conn); // from Loc
                fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(conn), false, conn); // to Loc
            }
        }
    } else {
        log4jDocInvoice.warn("Doc_Invoice - DocumentType unknown: " + this.DocumentType);
        fact = null;
    }
    SeqNo = "0";
    return fact;
}

From source file:org.openbravo.financial.paymentreport.erpCommon.ad_reports.PaymentReportDao.java

/**
 * This method creates a field provider with the information of the transaction
 * /*from ww  w .ja v  a2s .  c o m*/
 * @throws OBException
 */
private FieldProvider createFieldProviderForTransaction(FIN_FinaccTransaction transaction, String strGroupCrit,
        String strConvertCurrency, String strConversionDate) throws OBException {
    String dateFormatString = OBPropertiesProvider.getInstance().getOpenbravoProperties()
            .getProperty("dateFormat.java");
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatString);
    BigDecimal transAmount = null;
    ConversionRate convRate = null;

    // call with null to return empty map without any link to a dal object
    FieldProvider transactionData = FieldProviderFactory.getFieldProvider(null);

    // bp_group -- bp_category
    if (transaction.getBusinessPartner() != null) {
        FieldProviderFactory.setField(transactionData, "BP_GROUP",
                transaction.getBusinessPartner().getBusinessPartnerCategory().getName());
        // bpartner
        FieldProviderFactory.setField(transactionData, "BPARTNER", transaction.getBusinessPartner().getName());
    } else {
        // bp_group -- bp_category & bpartner
        FieldProviderFactory.setField(transactionData, "BP_GROUP", "");
        FieldProviderFactory.setField(transactionData, "BPARTNER", "");
    }
    // transCurrency
    FieldProviderFactory.setField(transactionData, "TRANS_CURRENCY", transaction.getCurrency().getISOCode());
    // paymentMethod
    FieldProviderFactory.setField(transactionData, "PAYMENT_METHOD", "");
    // payment
    FieldProviderFactory.setField(transactionData, "PAYMENT", "");
    // description
    FieldProviderFactory.setField(transactionData, "PAYMENT_DESC", transaction.getDescription());
    // payment_id
    FieldProviderFactory.setField(transactionData, "PAYMENT_ID", "");
    // payment_date
    FieldProviderFactory.setField(transactionData, "PAYMENT_DATE",
            dateFormat.format(transaction.getDateAcct()));
    // payment_docNo
    FieldProviderFactory.setField(transactionData, "PAYMENT_DOCNO", "");
    // payment yes / no
    FieldProviderFactory.setField(transactionData, "PAYMENT_Y_N", "Display:None");
    // financialAccount
    FieldProviderFactory.setField(transactionData, "FINANCIAL_ACCOUNT", transaction.getAccount().getName());
    // status
    FieldProviderFactory.setField(transactionData, "STATUS", translateRefList(transaction.getStatus()));
    FieldProviderFactory.setField(transactionData, "STATUS_CODE", transaction.getStatus());
    // is receipt
    if (transaction.getStatus().equals("PWNC")) {
        FieldProviderFactory.setField(transactionData, "ISRECEIPT", "Y");
        // isReceipt = true;
    } else if (transaction.getStatus().equals("RDNC")) {
        FieldProviderFactory.setField(transactionData, "ISRECEIPT", "N");
        // isReceipt = false;
    }
    // deposit/withdraw date
    FieldProviderFactory.setField(transactionData, "DEPOSIT_WITHDRAW_DATE",
            dateFormat.format(transaction.getDateAcct()));
    // project
    FieldProviderFactory.setField(transactionData, "PROJECT", "");
    // salesPerson
    FieldProviderFactory.setField(transactionData, "SALES_PERSON", "");
    // invoiceNumber.
    FieldProviderFactory.setField(transactionData, "INVOICE_NUMBER", "");
    // payment plan id
    FieldProviderFactory.setField(transactionData, "PAYMENT_PLAN_ID", "");
    // payment plan yes / no
    FieldProviderFactory.setField(transactionData, "PAYMENT_PLAN_Y_N", "Display:none");
    // payment plan yes / no
    FieldProviderFactory.setField(transactionData, "NOT_PAYMENT_PLAN_Y_N", "Display:none");
    // invoiceDate
    FieldProviderFactory.setField(transactionData, "INVOICE_DATE", "");
    // dueDate.
    FieldProviderFactory.setField(transactionData, "DUE_DATE", dateFormat.format(transaction.getDateAcct()));
    // expectedDate.
    FieldProviderFactory.setField(transactionData, "EXPECTED_DATE",
            dateFormat.format(transaction.getDateAcct()));
    // plannedDSO
    FieldProviderFactory.setField(transactionData, "PLANNED_DSO", "0");
    // currentDSO
    FieldProviderFactory.setField(transactionData, "CURRENT_DSO", "0");
    // daysOverdue
    FieldProviderFactory.setField(transactionData, "OVERDUE", "0");

    // transactional and base amounts
    transAmount = transaction.getDepositAmount().subtract(transaction.getPaymentAmount());

    Currency baseCurrency = OBDal.getInstance().get(Currency.class, strConvertCurrency);

    boolean sameCurrency = baseCurrency.getISOCode().equalsIgnoreCase(transaction.getCurrency().getISOCode());

    if (!sameCurrency) {
        convRate = this.getConversionRate(transaction.getCurrency(), baseCurrency, strConversionDate);

        if (convRate != null) {
            final int stdPrecission = convRate.getToCurrency().getStandardPrecision().intValue();
            FieldProviderFactory.setField(transactionData, "TRANS_AMOUNT", transAmount.toString());
            FieldProviderFactory.setField(transactionData, "BASE_AMOUNT",
                    transAmount.multiply(convRate.getMultipleRateBy())
                            .setScale(stdPrecission, BigDecimal.ROUND_HALF_UP).toString());
        } else {
            String message = transaction.getCurrency().getISOCode() + " -> " + baseCurrency.getISOCode() + " "
                    + strConversionDate;

            throw new OBException(message);
        }
    } else {
        // convRate = null;
        FieldProviderFactory.setField(transactionData, "TRANS_AMOUNT", transAmount.toString());
        FieldProviderFactory.setField(transactionData, "BASE_AMOUNT", transAmount.toString());
    }
    // currency
    FieldProviderFactory.setField(transactionData, "BASE_CURRENCY", baseCurrency.getISOCode());
    // group_crit_id this is the column that has the ids of the grouping criteria selected
    if (strGroupCrit.equalsIgnoreCase("APRM_FATS_BPARTNER")) {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID", transactionData.getField("BPARTNER"));
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "Business Partner");
    } else if (strGroupCrit.equalsIgnoreCase("Project")) {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID", transactionData.getField("PROJECT"));
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "Project");
    } else if (strGroupCrit.equalsIgnoreCase("FINPR_BPartner_Category")) {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID", transactionData.getField("BP_GROUP"));
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "Business Partner Category");
    } else if (strGroupCrit.equalsIgnoreCase("INS_CURRENCY")) {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID",
                transactionData.getField("TRANS_CURRENCY"));
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "Currency");
    } else if (strGroupCrit.equalsIgnoreCase("ACCS_ACCOUNT_ID_D")) {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID",
                transactionData.getField("FINANCIAL_ACCOUNT"));
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "Financial Account");
    } else {
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT_ID", "");
        FieldProviderFactory.setField(transactionData, "GROUP_CRIT", "");
    }

    return transactionData;
}

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

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

    String returnId = (String) context.get("returnId");
    List<GenericValue> billItems = UtilGenerics.checkList(context.get("billItems"));
    String errorMsg = UtilProperties.getMessage(resource, "AccountingErrorCreatingInvoiceForReturn",
            UtilMisc.toMap("returnId", returnId), locale);
    // List invoicesCreated = new ArrayList();
    try {//from www . ja  v  a 2 s  .c om
        String invoiceTypeId;
        String description;
        // get the return header
        GenericValue returnHeader = EntityQuery.use(delegator).from("ReturnHeader").where("returnId", returnId)
                .queryOne();
        if (returnHeader == null || returnHeader.get("returnHeaderTypeId") == null) {
            return ServiceUtil.returnError("Return type cannot be null");
        }

        if (returnHeader.getString("returnHeaderTypeId").startsWith("CUSTOMER_")) {
            invoiceTypeId = "CUST_RTN_INVOICE";
            description = "Return Invoice for Customer Return #" + returnId;
        } else {
            invoiceTypeId = "PURC_RTN_INVOICE";
            description = "Return Invoice for Vendor Return #" + returnId;
        }
        // set the invoice data
        Map<String, Object> input = UtilMisc.<String, Object>toMap("invoiceTypeId", invoiceTypeId, "statusId",
                "INVOICE_IN_PROCESS");
        input.put("partyId", returnHeader.get("toPartyId"));
        input.put("partyIdFrom", returnHeader.get("fromPartyId"));
        input.put("currencyUomId", returnHeader.get("currencyUomId"));
        input.put("invoiceDate", UtilDateTime.nowTimestamp());
        input.put("description", description);
        input.put("billingAccountId", returnHeader.get("billingAccountId"));
        input.put("userLogin", userLogin);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        // return the invoiceId
        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("invoiceId", invoiceId);
        return results;
    } catch (GenericServiceException e) {
        Debug.logError(e, errorMsg + e.getMessage(), module);
        return ServiceUtil.returnError(errorMsg + e.getMessage());
    } catch (GenericEntityException e) {
        Debug.logError(e, errorMsg + e.getMessage(), module);
        return ServiceUtil.returnError(errorMsg + e.getMessage());
    }
}

From source file:org.kuali.ole.module.purap.document.service.impl.PaymentRequestServiceImpl.java

/**
 * Generates a PurAP accounting line and adds to the specified tax item.
 *
 * @param taxItem       The specified tax item the accounting line will be associated with.
 * @param taxableAmount The amount to which tax is computed against.
 * @return A fully populated PurApAccountingLine instance for the specified tax item.
 *///from  w w w .  j  a v a  2 s  .  c o m
protected PurApAccountingLine addTaxAccountingLine(PurApItem taxItem, BigDecimal taxableAmount) {
    PaymentRequestDocument preq = taxItem.getPurapDocument();
    PurApAccountingLine taxLine = null;

    try {
        taxLine = (PurApAccountingLine) taxItem.getAccountingLineClass().newInstance();
    } catch (IllegalAccessException e) {
        throw new IllegalArgumentException("Unable to access sourceAccountingLineClass", e);
    } catch (InstantiationException e) {
        throw new IllegalArgumentException("Unable to instantiate sourceAccountingLineClass", e);
    }

    // tax item type indicators
    boolean isFederalTax = ItemTypeCodes.ITEM_TYPE_FEDERAL_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederalGross = ItemTypeCodes.ITEM_TYPE_FEDERAL_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateTax = ItemTypeCodes.ITEM_TYPE_STATE_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateGross = ItemTypeCodes.ITEM_TYPE_STATE_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederal = isFederalTax || isFederalGross; // true for federal tax/gross; false for state tax/gross
    boolean isGross = isFederalGross || isStateGross; // true for federal/state gross, false for federal/state tax

    // obtain accounting line info according to tax item type code
    String taxChart = null;
    String taxAccount = null;
    String taxObjectCode = null;

    if (isGross) {
        // for gross up tax items, use preq's first item's first accounting line, which shall exist at this point
        AccountingLine line1 = preq.getFirstAccount();
        taxChart = line1.getChartOfAccountsCode();
        taxAccount = line1.getAccountNumber();
        taxObjectCode = line1.getFinancialObjectCode();
    } else if (isFederalTax) {
        // for federal tax item, get chart, account, object code info from parameters
        taxChart = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                preq.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve federal tax parameters.");
            throw new RuntimeException("Unable to retrieve federal tax parameters.");
        }
    } else if (isStateTax) {
        // for state tax item, get chart, account, object code info from parameters
        taxChart = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                preq.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve state tax parameters.");
            throw new RuntimeException("Unable to retrieve state tax parameters.");
        }
    }

    // calculate tax amount according to gross up indicator and federal/state tax type
    /*
     * The formula of tax and gross up amount are as follows: if (not gross up) gross not existing taxFederal/State = - amount *
     * rateFederal/State otherwise gross up grossFederal/State = amount * rateFederal/State / (1 - rateFederal - rateState) tax
     * = - gross
     */

    // pick federal/state tax rate
    BigDecimal taxPercentFederal = preq.getTaxFederalPercent();
    BigDecimal taxPercentState = preq.getTaxStatePercent();
    BigDecimal taxPercent = isFederal ? taxPercentFederal : taxPercentState;

    // divider value according to gross up or not
    BigDecimal taxDivider = new BigDecimal(100);
    if (preq.getTaxGrossUpIndicator()) {
        taxDivider = taxDivider.subtract(taxPercentFederal.add(taxPercentState));
    }

    // tax = amount * rate / divider
    BigDecimal taxAmount = taxableAmount.multiply(taxPercent);
    taxAmount = taxAmount.divide(taxDivider, 5, BigDecimal.ROUND_HALF_UP);

    // tax is always negative, since it reduces the total amount; while gross up is always the positive of tax
    if (!isGross) {
        taxAmount = taxAmount.negate();
    }

    // populate necessary accounting line fields
    taxLine.setDocumentNumber(preq.getDocumentNumber());
    taxLine.setSequenceNumber(preq.getNextSourceLineNumber());
    taxLine.setChartOfAccountsCode(taxChart);
    taxLine.setAccountNumber(taxAccount);
    taxLine.setFinancialObjectCode(taxObjectCode);
    taxLine.setAmount(new KualiDecimal(taxAmount));

    // add the accounting line to the item
    taxLine.setItemIdentifier(taxItem.getItemIdentifier());
    taxLine.setPurapItem(taxItem);
    taxItem.getSourceAccountingLines().add(taxLine);

    return taxLine;
}

From source file:org.kuali.kfs.module.purap.document.service.impl.PaymentRequestServiceImpl.java

/**
 * Generates a PurAP accounting line and adds to the specified tax item.
 *
 * @param taxItem The specified tax item the accounting line will be associated with.
 * @param taxableAmount The amount to which tax is computed against.
 * @return A fully populated PurApAccountingLine instance for the specified tax item.
 *///from www. ja  v a  2s.com
protected PurApAccountingLine addTaxAccountingLine(PurApItem taxItem, BigDecimal taxableAmount) {
    PaymentRequestDocument preq = taxItem.getPurapDocument();
    PurApAccountingLine taxLine = null;

    try {
        taxLine = (PurApAccountingLine) taxItem.getAccountingLineClass().newInstance();
    } catch (IllegalAccessException e) {
        throw new InfrastructureException("Unable to access sourceAccountingLineClass", e);
    } catch (InstantiationException e) {
        throw new InfrastructureException("Unable to instantiate sourceAccountingLineClass", e);
    }

    // tax item type indicators
    boolean isFederalTax = ItemTypeCodes.ITEM_TYPE_FEDERAL_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederalGross = ItemTypeCodes.ITEM_TYPE_FEDERAL_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateTax = ItemTypeCodes.ITEM_TYPE_STATE_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateGross = ItemTypeCodes.ITEM_TYPE_STATE_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederal = isFederalTax || isFederalGross; // true for federal tax/gross; false for state tax/gross
    boolean isGross = isFederalGross || isStateGross; // true for federal/state gross, false for federal/state tax

    // obtain accounting line info according to tax item type code
    String taxChart = null;
    String taxAccount = null;
    String taxObjectCode = null;

    if (isGross) {
        // for gross up tax items, use preq's first item's first accounting line, which shall exist at this point
        AccountingLine line1 = preq.getFirstAccount();
        taxChart = line1.getChartOfAccountsCode();
        taxAccount = line1.getAccountNumber();
        taxObjectCode = line1.getFinancialObjectCode();
    } else if (isFederalTax) {
        // for federal tax item, get chart, account, object code info from parameters
        taxChart = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                preq.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve federal tax parameters.");
            throw new RuntimeException("Unable to retrieve federal tax parameters.");
        }
    } else if (isStateTax) {
        // for state tax item, get chart, account, object code info from parameters
        taxChart = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = parameterService.getParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(PaymentRequestDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                preq.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve state tax parameters.");
            throw new RuntimeException("Unable to retrieve state tax parameters.");
        }
    }

    // calculate tax amount according to gross up indicator and federal/state tax type
    /*
     * The formula of tax and gross up amount are as follows: if (not gross up) gross not existing taxFederal/State = - amount *
     * rateFederal/State otherwise gross up grossFederal/State = amount * rateFederal/State / (1 - rateFederal - rateState) tax
     * = - gross
     */

    // pick federal/state tax rate
    BigDecimal taxPercentFederal = preq.getTaxFederalPercent();
    BigDecimal taxPercentState = preq.getTaxStatePercent();
    BigDecimal taxPercent = isFederal ? taxPercentFederal : taxPercentState;

    // divider value according to gross up or not
    BigDecimal taxDivider = new BigDecimal(100);
    if (preq.getTaxGrossUpIndicator()) {
        taxDivider = taxDivider.subtract(taxPercentFederal.add(taxPercentState));
    }

    // tax = amount * rate / divider
    BigDecimal taxAmount = taxableAmount.multiply(taxPercent);
    taxAmount = taxAmount.divide(taxDivider, 5, BigDecimal.ROUND_HALF_UP);

    // tax is always negative, since it reduces the total amount; while gross up is always the positive of tax
    if (!isGross) {
        taxAmount = taxAmount.negate();
    }

    // populate necessary accounting line fields
    taxLine.setDocumentNumber(preq.getDocumentNumber());
    taxLine.setSequenceNumber(preq.getNextSourceLineNumber());
    taxLine.setChartOfAccountsCode(taxChart);
    taxLine.setAccountNumber(taxAccount);
    taxLine.setFinancialObjectCode(taxObjectCode);
    taxLine.setAmount(new KualiDecimal(taxAmount));

    // add the accounting line to the item
    taxLine.setItemIdentifier(taxItem.getItemIdentifier());
    taxLine.setPurapItem(taxItem);
    taxItem.getSourceAccountingLines().add(taxLine);

    return taxLine;
}

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

public static void reserveInventory(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin,
        Locale locale, List<GenericValue> orderItemShipGroupInfo, List<String> dropShipGroupIds,
        Map<String, GenericValue> itemValuesBySeqId, String orderTypeId, String productStoreId,
        List<String> resErrorMessages) throws GeneralException {
    boolean isImmediatelyFulfilled = false;
    GenericValue productStore = null;// w ww .  j  a  va  2  s  .c  om
    if (UtilValidate.isNotEmpty(productStoreId)) {
        try {
            productStore = delegator.findByPrimaryKeyCache("ProductStore",
                    UtilMisc.toMap("productStoreId", productStoreId));
        } catch (GenericEntityException e) {
            throw new GeneralException(
                    UtilProperties.getMessage(resource_error, "OrderErrorCouldNotFindProductStoreWithID",
                            UtilMisc.toMap("productStoreId", productStoreId), locale) + e.toString());
        }
    }
    if (productStore != null) {
        isImmediatelyFulfilled = "Y".equals(productStore.getString("isImmediatelyFulfilled"));
    }

    boolean reserveInventory = ("SALES_ORDER".equals(orderTypeId));
    if (reserveInventory && isImmediatelyFulfilled) {
        // don't reserve inventory if the product store has isImmediatelyFulfilled set, ie don't if in this store things are immediately fulfilled
        reserveInventory = false;
    }

    // START inventory reservation
    // decrement inventory available for each OrderItemShipGroupAssoc, within the same transaction
    if (UtilValidate.isNotEmpty(orderItemShipGroupInfo)) {
        Iterator<GenericValue> osiInfos = orderItemShipGroupInfo.iterator();
        while (osiInfos.hasNext()) {
            GenericValue orderItemShipGroupAssoc = osiInfos.next();
            if ("OrderItemShipGroupAssoc".equals(orderItemShipGroupAssoc.getEntityName())) {
                if (dropShipGroupIds != null
                        && dropShipGroupIds.contains(orderItemShipGroupAssoc.getString("shipGroupSeqId"))) {
                    // the items in the drop ship groups are not reserved
                    continue;
                }
                GenericValue orderItem = itemValuesBySeqId.get(orderItemShipGroupAssoc.get("orderItemSeqId"));
                GenericValue orderItemShipGroup = orderItemShipGroupAssoc.getRelatedOne("OrderItemShipGroup");
                String shipGroupFacilityId = orderItemShipGroup.getString("facilityId");
                String itemStatus = orderItem.getString("statusId");
                if ("ITEM_REJECTED".equals(itemStatus) || "ITEM_CANCELLED".equals(itemStatus)
                        || "ITEM_COMPLETED".equals(itemStatus)) {
                    Debug.logInfo("Order item [" + orderItem.getString("orderId") + " / "
                            + orderItem.getString("orderItemSeqId")
                            + "] is not in a proper status for reservation", module);
                    continue;
                }
                if (UtilValidate.isNotEmpty(orderItem.getString("productId")) && // only reserve product items, ignore non-product items
                        !"RENTAL_ORDER_ITEM".equals(orderItem.getString("orderItemTypeId"))) { // ignore for rental
                    try {
                        // get the product of the order item
                        GenericValue product = orderItem.getRelatedOne("Product");
                        if (product == null) {
                            Debug.logError("Error when looking up product in reserveInventory service", module);
                            resErrorMessages.add("Error when looking up product in reserveInventory service");
                            continue;
                        }
                        if (reserveInventory) {
                            // for MARKETING_PKG_PICK reserve the components
                            if (EntityTypeUtil.hasParentType(delegator, "ProductType", "productTypeId",
                                    product.getString("productTypeId"), "parentTypeId", "MARKETING_PKG_PICK")) {
                                Map<String, Object> componentsRes = dispatcher.runSync("getAssociatedProducts",
                                        UtilMisc.toMap("productId", orderItem.getString("productId"), "type",
                                                "PRODUCT_COMPONENT"));
                                if (ServiceUtil.isError(componentsRes)) {
                                    resErrorMessages
                                            .add((String) componentsRes.get(ModelService.ERROR_MESSAGE));
                                    continue;
                                } else {
                                    List<GenericValue> assocProducts = UtilGenerics
                                            .checkList(componentsRes.get("assocProducts"));
                                    Iterator<GenericValue> assocProductsIter = assocProducts.iterator();
                                    while (assocProductsIter.hasNext()) {
                                        GenericValue productAssoc = assocProductsIter.next();
                                        BigDecimal quantityOrd = productAssoc.getBigDecimal("quantity");
                                        BigDecimal quantityKit = orderItemShipGroupAssoc
                                                .getBigDecimal("quantity");
                                        BigDecimal quantity = quantityOrd.multiply(quantityKit);
                                        Map<String, Object> reserveInput = new HashMap<String, Object>();
                                        reserveInput.put("productStoreId", productStoreId);
                                        reserveInput.put("productId", productAssoc.getString("productIdTo"));
                                        reserveInput.put("orderId", orderItem.getString("orderId"));
                                        reserveInput.put("orderItemSeqId",
                                                orderItem.getString("orderItemSeqId"));
                                        reserveInput.put("shipGroupSeqId",
                                                orderItemShipGroupAssoc.getString("shipGroupSeqId"));
                                        reserveInput.put("quantity", quantity);
                                        reserveInput.put("userLogin", userLogin);
                                        reserveInput.put("facilityId", shipGroupFacilityId);
                                        Map<String, Object> reserveResult = dispatcher
                                                .runSync("reserveStoreInventory", reserveInput);

                                        if (ServiceUtil.isError(reserveResult)) {
                                            String invErrMsg = "The product ";
                                            if (product != null) {
                                                invErrMsg += getProductName(product, orderItem);
                                            }
                                            invErrMsg += " with ID " + orderItem.getString("productId")
                                                    + " is no longer in stock. Please try reducing the quantity or removing the product from this order.";
                                            resErrorMessages.add(invErrMsg);
                                        }
                                    }
                                }
                            } else {
                                // reserve the product
                                Map<String, Object> reserveInput = new HashMap<String, Object>();
                                reserveInput.put("productStoreId", productStoreId);
                                reserveInput.put("productId", orderItem.getString("productId"));
                                reserveInput.put("orderId", orderItem.getString("orderId"));
                                reserveInput.put("orderItemSeqId", orderItem.getString("orderItemSeqId"));
                                reserveInput.put("shipGroupSeqId",
                                        orderItemShipGroupAssoc.getString("shipGroupSeqId"));
                                reserveInput.put("facilityId", shipGroupFacilityId);
                                // use the quantity from the orderItemShipGroupAssoc, NOT the orderItem, these are reserved by item-group assoc
                                reserveInput.put("quantity", orderItemShipGroupAssoc.getBigDecimal("quantity"));
                                reserveInput.put("userLogin", userLogin);
                                Map<String, Object> reserveResult = dispatcher.runSync("reserveStoreInventory",
                                        reserveInput);

                                if (ServiceUtil.isError(reserveResult)) {
                                    String invErrMsg = "The product ";
                                    if (product != null) {
                                        invErrMsg += getProductName(product, orderItem);
                                    }
                                    invErrMsg += " with ID " + orderItem.getString("productId")
                                            + " is no longer in stock. Please try reducing the quantity or removing the product from this order.";
                                    resErrorMessages.add(invErrMsg);
                                }
                            }
                        }
                        // Reserving inventory or not we still need to create a marketing package
                        // If the product is a marketing package auto, attempt to create enough packages to bring ATP back to 0, won't necessarily create enough to cover this order.
                        if (EntityTypeUtil.hasParentType(delegator, "ProductType", "productTypeId",
                                product.getString("productTypeId"), "parentTypeId", "MARKETING_PKG_AUTO")) {
                            // do something tricky here: run as the "system" user
                            // that can actually create and run a production run
                            GenericValue permUserLogin = delegator.findByPrimaryKeyCache("UserLogin",
                                    UtilMisc.toMap("userLoginId", "system"));
                            Map<String, Object> inputMap = new HashMap<String, Object>();
                            if (UtilValidate.isNotEmpty(shipGroupFacilityId)) {
                                inputMap.put("facilityId", shipGroupFacilityId);
                            } else {
                                inputMap.put("facilityId", productStore.getString("inventoryFacilityId"));
                            }
                            inputMap.put("orderId", orderItem.getString("orderId"));
                            inputMap.put("orderItemSeqId", orderItem.getString("orderItemSeqId"));
                            inputMap.put("userLogin", permUserLogin);
                            Map<String, Object> prunResult = dispatcher.runSync("createProductionRunForMktgPkg",
                                    inputMap);
                            if (ServiceUtil.isError(prunResult)) {
                                Debug.logError(
                                        ServiceUtil.getErrorMessage(prunResult) + " for input:" + inputMap,
                                        module);
                            }
                        }
                    } catch (GenericServiceException e) {
                        String errMsg = "Fatal error calling reserveStoreInventory service: " + e.toString();
                        Debug.logError(e, errMsg, module);
                        resErrorMessages.add(errMsg);
                    }
                }
            }
        }
    }
}

From source file:org.kuali.ole.module.purap.document.service.impl.InvoiceServiceImpl.java

/**
 * Generates a PurAP accounting line and adds to the specified tax item.
 *
 * @param taxItem       The specified tax item the accounting line will be associated with.
 * @param taxableAmount The amount to which tax is computed against.
 * @return A fully populated PurApAccountingLine instance for the specified tax item.
 *///from w  w  w  . j a va2 s .c  o  m
protected PurApAccountingLine addTaxAccountingLine(PurApItem taxItem, BigDecimal taxableAmount) {
    InvoiceDocument prqs = taxItem.getPurapDocument();
    PurApAccountingLine taxLine = null;

    try {
        taxLine = (PurApAccountingLine) taxItem.getAccountingLineClass().newInstance();
    } catch (IllegalAccessException e) {
        throw new IllegalArgumentException("Unable to access sourceAccountingLineClass", e);
    } catch (InstantiationException e) {
        throw new IllegalArgumentException("Unable to instantiate sourceAccountingLineClass", e);
    }

    // tax item type indicators
    boolean isFederalTax = ItemTypeCodes.ITEM_TYPE_FEDERAL_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederalGross = ItemTypeCodes.ITEM_TYPE_FEDERAL_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateTax = ItemTypeCodes.ITEM_TYPE_STATE_TAX_CODE.equals(taxItem.getItemTypeCode());
    boolean isStateGross = ItemTypeCodes.ITEM_TYPE_STATE_GROSS_CODE.equals(taxItem.getItemTypeCode());
    boolean isFederal = isFederalTax || isFederalGross; // true for federal tax/gross; false for state tax/gross
    boolean isGross = isFederalGross || isStateGross; // true for federal/state gross, false for federal/state tax

    // obtain accounting line info according to tax item type code
    String taxChart = null;
    String taxAccount = null;
    String taxObjectCode = null;

    if (isGross) {
        // for gross up tax items, use prqs's first item's first accounting line, which shall exist at this point
        AccountingLine line1 = prqs.getFirstAccount();
        taxChart = line1.getChartOfAccountsCode();
        taxAccount = line1.getAccountNumber();
        taxObjectCode = line1.getFinancialObjectCode();
    } else if (isFederalTax) {
        // for federal tax item, get chart, account, object code info from parameters
        taxChart = getParameter(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE,
                OLEConstants.InvoiceDocument.CMPNT_CD,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = getParameter(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE,
                OLEConstants.InvoiceDocument.CMPNT_CD,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(InvoiceDocument.class,
                NRATaxParameters.FEDERAL_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                prqs.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve federal tax parameters.");
            throw new RuntimeException("Unable to retrieve federal tax parameters.");
        }
    } else if (isStateTax) {
        // for state tax item, get chart, account, object code info from parameters
        taxChart = getParameter(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE,
                OLEConstants.InvoiceDocument.CMPNT_CD,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_CHART_SUFFIX);
        taxAccount = getParameter(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE,
                OLEConstants.InvoiceDocument.CMPNT_CD,
                NRATaxParameters.STATE_TAX_PARM_PREFIX + NRATaxParameters.TAX_PARM_ACCOUNT_SUFFIX);
        taxObjectCode = parameterService.getSubParameterValueAsString(InvoiceDocument.class,
                NRATaxParameters.STATE_TAX_PARM_PREFIX
                        + NRATaxParameters.TAX_PARM_OBJECT_BY_INCOME_CLASS_SUFFIX,
                prqs.getTaxClassificationCode());
        if (StringUtils.isBlank(taxChart) || StringUtils.isBlank(taxAccount)
                || StringUtils.isBlank(taxObjectCode)) {
            LOG.error("Unable to retrieve state tax parameters.");
            throw new RuntimeException("Unable to retrieve state tax parameters.");
        }
    }

    // calculate tax amount according to gross up indicator and federal/state tax type
    /*
     * The formula of tax and gross up amount are as follows: if (not gross up) gross not existing taxFederal/State = - amount *
     * rateFederal/State otherwise gross up grossFederal/State = amount * rateFederal/State / (1 - rateFederal - rateState) tax
     * = - gross
     */

    // pick federal/state tax rate
    BigDecimal taxPercentFederal = prqs.getTaxFederalPercent();
    BigDecimal taxPercentState = prqs.getTaxStatePercent();
    BigDecimal taxPercent = isFederal ? taxPercentFederal : taxPercentState;

    // divider value according to gross up or not
    BigDecimal taxDivider = new BigDecimal(100);
    if (prqs.getTaxGrossUpIndicator()) {
        taxDivider = taxDivider.subtract(taxPercentFederal.add(taxPercentState));
    }

    // tax = amount * rate / divider
    BigDecimal taxAmount = taxableAmount.multiply(taxPercent);
    taxAmount = taxAmount.divide(taxDivider, 5, BigDecimal.ROUND_HALF_UP);

    // tax is always negative, since it reduces the total amount; while gross up is always the positive of tax
    if (!isGross) {
        taxAmount = taxAmount.negate();
    }

    // populate necessary accounting line fields
    taxLine.setDocumentNumber(prqs.getDocumentNumber());
    taxLine.setSequenceNumber(prqs.getNextSourceLineNumber());
    taxLine.setChartOfAccountsCode(taxChart);
    taxLine.setAccountNumber(taxAccount);
    taxLine.setFinancialObjectCode(taxObjectCode);
    taxLine.setAmount(new KualiDecimal(taxAmount));

    // add the accounting line to the item
    taxLine.setItemIdentifier(taxItem.getItemIdentifier());
    taxLine.setPurapItem(taxItem);
    taxItem.getSourceAccountingLines().add(taxLine);

    return taxLine;
}