org.openbravo.advpaymentmngt.process.FIN_PaymentMonitorProcess.java Source code

Java tutorial

Introduction

Here is the source code for org.openbravo.advpaymentmngt.process.FIN_PaymentMonitorProcess.java

Source

/*
 *************************************************************************
 * The contents of this file are subject to the Openbravo  Public  License
 * Version  1.0  (the  "License"),  being   the  Mozilla   Public  License
 * Version 1.1  with a permitted attribution clause; you may not  use this
 * file except in compliance with the License. You  may  obtain  a copy of
 * the License at http://www.openbravo.com/legal/license.html
 * Software distributed under the License  is  distributed  on  an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific  language  governing  rights  and  limitations
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
 * All portions are Copyright (C) 2010-2015 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 *************************************************************************
 */

package org.openbravo.advpaymentmngt.process;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openbravo.advpaymentmngt.utility.FIN_Utility;
import org.openbravo.base.exception.OBException;
import org.openbravo.base.session.OBPropertiesProvider;
import org.openbravo.dal.core.OBContext;
import org.openbravo.dal.service.OBCriteria;
import org.openbravo.dal.service.OBDal;
import org.openbravo.dal.service.OBQuery;
import org.openbravo.database.ConnectionProvider;
import org.openbravo.erpCommon.ad_forms.AcctServer;
import org.openbravo.erpCommon.businessUtility.Preferences;
import org.openbravo.erpCommon.utility.PropertyException;
import org.openbravo.erpCommon.utility.PropertyNotFoundException;
import org.openbravo.model.ad.domain.Preference;
import org.openbravo.model.ad.module.Module;
import org.openbravo.model.common.invoice.Invoice;
import org.openbravo.model.financialmgmt.payment.DebtPayment;
import org.openbravo.model.financialmgmt.payment.FIN_Payment;
import org.openbravo.model.financialmgmt.payment.FIN_PaymentSchedInvV;
import org.openbravo.model.financialmgmt.payment.FIN_PaymentSchedule;
import org.openbravo.model.financialmgmt.payment.FIN_PaymentScheduleDetail;
import org.openbravo.scheduling.ProcessBundle;
import org.openbravo.scheduling.ProcessLogger;
import org.openbravo.service.db.DalBaseProcess;
import org.openbravo.service.db.DalConnectionProvider;
import org.quartz.JobExecutionException;

public class FIN_PaymentMonitorProcess extends DalBaseProcess {
    private static ProcessLogger logger;

    public void doExecute(ProcessBundle bundle) throws Exception {
        logger = bundle.getLogger();
        // Check to know if PaymentMonitor property is set in the system.
        try {
            Preferences.getPreferenceValue("PaymentMonitor", true, null, null, OBContext.getOBContext().getUser(),
                    null, null);
        } catch (PropertyNotFoundException e) {
            logger.log("Property not found \n");
            return;
        } catch (PropertyException e) {
            logger.log("PropertyException, there is a conflict for PaymentMonitor property\n");
            return;
        }
        // Check to know that this APR is the module implementing the PaymentMonitor property
        if (isPreferenceOfModule("PaymentMonitor", "A918E3331C404B889D69AA9BFAFB23AC")) {
            logger.log("Starting Update Paid Amount for Invoices Background Process.\n");
        } else {
            logger.log("Payment Monitor active for other module.\n");
            logger.log("Core's background process is executed.\n");
            return;
        }

        ScrollableResults invoiceScroller = null;
        try {
            int counter = 0;
            final Module migration = OBDal.getInstance().get(Module.class, "4BD3D4B262B048518FE62496EF09D549");

            StringBuilder whereClause = new StringBuilder();
            whereClause.append(" as i");
            whereClause.append("   left join i.fINPaymentScheduleList fps ");
            whereClause.append(" where i.processed=true");
            whereClause.append(" and (i.paymentComplete=false ");
            whereClause.append("      or fps.updated >= i.lastCalculatedOnDate ");
            whereClause.append("      or i.outstandingAmount <> 0");
            if (migration != null) {
                whereClause.append("  or (i.finalSettlementDate is null");
                whereClause.append(" and fps.id is not null");
                whereClause.append(" and i.aprmtIsmigrated = 'N'))");
            } else {
                whereClause.append(" or i.finalSettlementDate is null)");
            }

            final OBQuery<Invoice> obc = OBDal.getInstance().createQuery(Invoice.class, whereClause.toString());

            // For Background process execution at system level
            if (OBContext.getOBContext().isInAdministratorMode()) {
                obc.setFilterOnReadableClients(false);
                obc.setFilterOnReadableOrganization(false);
            }

            invoiceScroller = obc.scroll(ScrollMode.FORWARD_ONLY);
            while (invoiceScroller.next()) {
                final Invoice invoice = (Invoice) invoiceScroller.get()[0];
                updateInvoice(invoice);
                counter++;
                if (counter % 100 == 0) {
                    OBDal.getInstance().getSession().flush();
                    OBDal.getInstance().getSession().clear();
                    logger.log("Invoices updated: " + counter + "\n");
                }
            }
            if (counter % 100 != 0)
                logger.log("Invoices updated: " + counter + "\n");
        } catch (Exception e) {
            // catch any possible exception and throw it as a Quartz
            // JobExecutionException
            throw new JobExecutionException(e.getMessage(), e);
        } finally {
            if (invoiceScroller != null) {
                invoiceScroller.close();
            }
        }
    }

    /**
     * Updates the days till due and last calculated on date fields of the invoice.
     * 
     * @param invoice
     * @throws OBException
     */
    public static void updateInvoice(Invoice invoice) throws OBException {
        OBContext.setAdminMode();
        try {
            HashMap<String, BigDecimal> oldFlowAmounts = new HashMap<String, BigDecimal>();
            // If the invoice has old flow's related payments calculate its statuses and amounts
            if (invoice.getFinancialMgmtDebtPaymentList() != null
                    && invoice.getFinancialMgmtDebtPaymentList().size() > 0) {
                oldFlowAmounts = getOldflowAmounts(invoice.getFinancialMgmtDebtPaymentList(),
                        invoice.getCurrency().getId(), invoice.getAccountingDate());
            } else {
                oldFlowAmounts.put("paidAmt", BigDecimal.ZERO);
                oldFlowAmounts.put("outstandingAmt", BigDecimal.ZERO);
                oldFlowAmounts.put("overdueAmt", BigDecimal.ZERO);
            }

            HashMap<String, BigDecimal> amounts = calculateAmounts(invoice);
            invoice.setTotalPaid(amounts.get("paidAmt").add(oldFlowAmounts.get("paidAmt")));
            invoice.setOutstandingAmount(amounts.get("outstandingAmt").add(oldFlowAmounts.get("outstandingAmt")));
            invoice.setPaymentComplete(invoice.getOutstandingAmount().compareTo(BigDecimal.ZERO) == 0);
            invoice.setDueAmount(amounts.get("overdueAmt").add(oldFlowAmounts.get("overdueAmt")));
            invoice.setDaysTillDue(getDaysTillDue(invoice));
            if (invoice.getOutstandingAmount().compareTo(BigDecimal.ZERO) == 0) {
                Date finalSettlementDate = getFinalSettlementDate(invoice);
                // If date is null invoice amount = 0 then nothing to set
                if (finalSettlementDate != null) {
                    invoice.setFinalSettlementDate(finalSettlementDate);
                    invoice.setDaysSalesOutstanding(
                            FIN_Utility.getDaysBetween(invoice.getInvoiceDate(), finalSettlementDate));
                }
            }
            BigDecimal grandTotalAmount = invoice.getGrandTotalAmount();
            // This prevents division by ZERO
            if (grandTotalAmount.compareTo(BigDecimal.ZERO) == 0) {
                grandTotalAmount = BigDecimal.ONE;
            }
            invoice.setPercentageOverdue(amounts.get("overdue").multiply(new BigDecimal(100))
                    .divide(grandTotalAmount, BigDecimal.ROUND_HALF_UP).longValue());
            invoice.setLastCalculatedOnDate(new Date());

            OBDal.getInstance().save(invoice);
            OBDal.getInstance().flush();
        } catch (Exception e) {
        } finally {
            OBContext.restorePreviousMode();
        }
    }

    /**
     * Returns the date in which last payment for this invoice took place
     */
    private static Date getFinalSettlementDate(Invoice invoice) {
        final OBCriteria<FIN_PaymentSchedInvV> obc = OBDal.getInstance().createCriteria(FIN_PaymentSchedInvV.class);
        // For Background process execution at system level
        if (OBContext.getOBContext().isInAdministratorMode()) {
            obc.setFilterOnReadableClients(false);
            obc.setFilterOnReadableOrganization(false);
        }
        obc.add(Restrictions.eq(FIN_PaymentSchedInvV.PROPERTY_INVOICE, invoice));
        obc.setProjection(Projections.max(FIN_PaymentSchedInvV.PROPERTY_LASTPAYMENT));
        Object o = obc.list().get(0);
        if (o != null) {
            return ((Date) o);
        } else {
            return null;
        }
    }

    private static HashMap<String, BigDecimal> getOldflowAmounts(List<DebtPayment> debtPayments, String currencyTo,
            Date conversionDate) {
        BigDecimal paidAmt = BigDecimal.ZERO;
        BigDecimal outstandingAmt = BigDecimal.ZERO;
        BigDecimal overdueAmt = BigDecimal.ZERO;
        for (DebtPayment debtPayment : debtPayments) {
            // Calculate paid amount.
            BigDecimal paid = calculatePaidAmount(debtPayment, currencyTo, conversionDate, BigDecimal.ONE);
            paidAmt = paidAmt.add(paid);
            // Calculate outstanding amount.
            outstandingAmt = outstandingAmt.add(debtPayment.getAmount().subtract(paid));
            // Calculate overdue amount.
            overdueAmt = overdueAmt
                    .add(calculateOverdueAmount(debtPayment, currencyTo, conversionDate, BigDecimal.ONE));
        }
        HashMap<String, BigDecimal> amounts = new HashMap<String, BigDecimal>();
        amounts.put("paidAmt", paidAmt);
        amounts.put("outstandingAmt", outstandingAmt);
        amounts.put("overdueAmt", overdueAmt);
        return amounts;
    }

    private static HashMap<String, BigDecimal> calculateAmounts(Invoice invoice) {
        BigDecimal paidAmt = BigDecimal.ZERO;
        BigDecimal outstandingAmt = BigDecimal.ZERO;
        BigDecimal overdueAmt = BigDecimal.ZERO;
        BigDecimal overdue = BigDecimal.ZERO;
        for (FIN_PaymentSchedule paymentSchedule : invoice.getFINPaymentScheduleList()) {
            BigDecimal paid = BigDecimal.ZERO;
            for (FIN_PaymentScheduleDetail psd : paymentSchedule
                    .getFINPaymentScheduleDetailInvoicePaymentScheduleList()) {
                if (psd.isCanceled()) {
                    // If payment scheduled is cancelled don't consider its amount.
                    continue;
                }
                if (psd.getPaymentDetails() != null && FIN_Utility
                        .isPaymentConfirmed(psd.getPaymentDetails().getFinPayment().getStatus(), psd)) {
                    paid = paid.add(psd.getAmount().add(psd.getWriteoffAmount()));
                    // If an amount has been paid, let's check if any amount was paid late
                    Date paymentDate = psd.getPaymentDetails().getFinPayment().getPaymentDate();
                    Date dueDate = psd.getInvoicePaymentSchedule().getDueDate();
                    if (paymentDate.after(dueDate)) {
                        overdue = overdue.add(psd.getAmount());
                    }
                }
            }

            if (paymentSchedule.getPaidAmount().compareTo(paid) != 0) {
                if (logger != null) {
                    logger.log("ERROR Invoice " + invoice.getDocumentNo()
                            + ": wrong payment plan info, paid amount is "
                            + paymentSchedule.getPaidAmount().toPlainString() + " when it should be "
                            + paid.toPlainString());
                }
                paymentSchedule.setPaidAmount(paid);
                OBDal.getInstance().save(paymentSchedule);
            }
            if (paymentSchedule.getOutstandingAmount().compareTo(paymentSchedule.getAmount().subtract(paid)) != 0) {
                if (logger != null) {
                    logger.log("ERROR Invoice " + invoice.getDocumentNo()
                            + ": wrong payment plan info, outstanding amount is "
                            + paymentSchedule.getOutstandingAmount().toPlainString() + " when it should be "
                            + paymentSchedule.getAmount().subtract(paid).toPlainString());
                }
                paymentSchedule.setOutstandingAmount(paymentSchedule.getAmount().subtract(paid));
                OBDal.getInstance().save(paymentSchedule);
            }

            if (paymentSchedule.getDueDate().before(new Date())
                    && paymentSchedule.getOutstandingAmount() != BigDecimal.ZERO) {
                overdueAmt = overdueAmt.add(paymentSchedule.getOutstandingAmount());
            }
            paidAmt = paidAmt.add(paymentSchedule.getPaidAmount());
            outstandingAmt = outstandingAmt.add(paymentSchedule.getOutstandingAmount());
        }
        HashMap<String, BigDecimal> amounts = new HashMap<String, BigDecimal>();
        amounts.put("paidAmt", paidAmt);
        amounts.put("outstandingAmt", outstandingAmt);
        amounts.put("overdueAmt", overdueAmt);
        amounts.put("overdue", overdue);
        return amounts;
    }

    private static Long getDaysTillDue(Invoice invoice) {
        // Calculate days till due
        final OBCriteria<FIN_PaymentSchedule> obc = OBDal.getInstance().createCriteria(FIN_PaymentSchedule.class);
        // For Background process execution at system level
        if (OBContext.getOBContext().isInAdministratorMode()) {
            obc.setFilterOnReadableClients(false);
            obc.setFilterOnReadableOrganization(false);
        }
        obc.add(Restrictions.eq(FIN_PaymentSchedule.PROPERTY_INVOICE, invoice));
        obc.add(Restrictions.ne(FIN_PaymentSchedule.PROPERTY_OUTSTANDINGAMOUNT, BigDecimal.ZERO));
        obc.setProjection(Projections.min(FIN_PaymentSchedule.PROPERTY_DUEDATE));
        Object o = obc.list().get(0);
        if (o != null) {
            return (FIN_Utility.getDaysToDue((Date) o));
        } else {
            return 0L;
        }
    }

    /**
     * Checks if the module is implementing the specified property.
     * 
     * @param property
     *          Value of the property.
     * @param moduleId
     *          Module identifier.
     * @return true: only if there is one preference for the module or if there are several only one
     *         can be mark as selected. false: in other cases.
     */
    private static boolean isPreferenceOfModule(String property, String moduleId) {

        final OBCriteria<Preference> obcNotSel = OBDal.getInstance().createCriteria(Preference.class);
        obcNotSel.add(Restrictions.eq(Preference.PROPERTY_PROPERTY, property));
        obcNotSel.setFilterOnReadableClients(false);
        obcNotSel.setFilterOnReadableOrganization(false);

        final OBCriteria<Preference> obcSel = OBDal.getInstance().createCriteria(Preference.class);
        obcSel.add(Restrictions.eq(Preference.PROPERTY_PROPERTY, property));
        obcSel.add(Restrictions.eq(Preference.PROPERTY_SELECTED, true));
        obcSel.setFilterOnReadableClients(false);
        obcSel.setFilterOnReadableOrganization(false);

        if (obcNotSel.list() != null && obcNotSel.list().size() == 1) {
            return obcNotSel.list().get(0).getModule().getId().equals(moduleId);
        } else if (obcSel.list() != null && obcSel.list().size() == 1) {
            return obcSel.list().get(0).getModule().getId().equals(moduleId);
        } else {
            return false;
        }
    }

    public static BigDecimal calculatePaidAmount(DebtPayment payment, String strCurrencyTo, Date conversionDate,
            BigDecimal multiplier) {
        BigDecimal paidAmount = BigDecimal.ZERO;
        String finPaymentStatus = getMigratedPaymentStatus(payment);
        if ("PAID".equals(finPaymentStatus)) {
            return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                    strCurrencyTo, conversionDate, payment.getClient().getId(), payment.getOrganization().getId());
        } else if ("NOTPAID".equals(finPaymentStatus)) {
            return BigDecimal.ZERO;
        } else if (payment.getSettlementCancelled() == null) {
            return paidAmount;
        } else if (payment.getSettlementCancelled().getProcessed().equals("Y")) {
            if (payment.isPaymentComplete())
                return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                        strCurrencyTo, conversionDate, payment.getClient().getId(),
                        payment.getOrganization().getId());

            boolean paymentCompletelyPaid = true;
            for (DebtPayment cancelledPayment : payment.getSettlementCancelled()
                    .getFinancialMgmtDebtPaymentSettlementCancelledList()) {
                if (!cancelledPayment.isPaymentComplete()
                        && cancelledPayment.getAmount().compareTo(cancelledPayment.getWriteoffAmount()) != 0
                        && getMigratedPaymentStatus(cancelledPayment).equals("NOTMIGRATED")) {
                    // write off amount is equals to the payment's amount it is considered as paid
                    paymentCompletelyPaid = false;
                    break;
                } else if (getMigratedPaymentStatus(cancelledPayment).equals("NOTPAID")) {
                    paymentCompletelyPaid = false;
                    break;
                }
            }
            if (paymentCompletelyPaid) {
                // The sum of all canceled not paid payments in the settlement is zero. This means that the
                // payment has been paid completely, as it was canceled with some other pending payments
                // (for example, the ones comming from a credit memo)
                return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                        strCurrencyTo, conversionDate, payment.getClient().getId(),
                        payment.getOrganization().getId());
            }

            List<DebtPayment> generatedPayments = payment.getSettlementCancelled()
                    .getFinancialMgmtDebtPaymentCSettlementGenerateIDList();
            if (generatedPayments == null || generatedPayments.size() == 0) {
                return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                        strCurrencyTo, conversionDate, payment.getClient().getId(),
                        payment.getOrganization().getId());
            }
            BigDecimal generatedPaymentTotalAmount = BigDecimal.ZERO;
            BigDecimal generatedPaymentPaidAmount = BigDecimal.ZERO;
            for (DebtPayment generatedPayment : generatedPayments) {
                BigDecimal signMultiplier = generatedPayment.isReceipt() == payment.isReceipt() ? BigDecimal.ONE
                        : BigDecimal.ONE.negate();
                generatedPaymentTotalAmount = generatedPaymentTotalAmount
                        .add(getConvertedAmt(generatedPayment.getAmount(), generatedPayment.getCurrency().getId(),
                                strCurrencyTo, conversionDate, generatedPayment.getClient().getId(),
                                generatedPayment.getOrganization().getId()).multiply(signMultiplier));
                generatedPaymentPaidAmount = generatedPaymentPaidAmount.add(calculatePaidAmount(generatedPayment,
                        strCurrencyTo, generatedPayment.getSettlementGenerate().getAccountingDate(), BigDecimal.ONE)
                                .multiply(signMultiplier));
            }
            if (generatedPaymentTotalAmount.compareTo(BigDecimal.ZERO) == 0) {
                return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                        strCurrencyTo, conversionDate, payment.getClient().getId(),
                        payment.getOrganization().getId());
            }
            // payment amount * (generatedPaymentPaidAmount / generatedPaymentTotalAmount)
            BigDecimal paidAmountTmp = payment.getAmount().subtract(payment.getWriteoffAmount())
                    .multiply(generatedPaymentPaidAmount)
                    .divide(generatedPaymentTotalAmount, BigDecimal.ROUND_HALF_UP);
            // set scale of the currency using standard precision
            paidAmount = paidAmount.add(paidAmountTmp
                    .setScale(payment.getCurrency().getStandardPrecision().intValue(), BigDecimal.ROUND_HALF_UP));
            // Add payment's write off amount to the paid amount
            paidAmount = paidAmount.add(getConvertedAmt(payment.getWriteoffAmount(), payment.getCurrency().getId(),
                    strCurrencyTo, conversionDate, payment.getClient().getId(), payment.getOrganization().getId()));
        }
        return paidAmount;
    }

    public static BigDecimal calculateOverdueAmount(DebtPayment payment, String strCurrencyTo, Date conversionDate,
            BigDecimal multiplier) {
        BigDecimal overdueAmount = BigDecimal.ZERO;

        if (payment.getDueDate().compareTo(new Date(System.currentTimeMillis())) > 0) {
            return BigDecimal.ZERO;
        } else if ("PAID".equals(getMigratedPaymentStatus(payment))) {
            return BigDecimal.ZERO;
        } else if ("NOTPAID".equals(getMigratedPaymentStatus(payment))) {
            return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                    strCurrencyTo, conversionDate, payment.getClient().getId(), payment.getOrganization().getId());
        } else if (payment.getSettlementCancelled() == null) {
            return getConvertedAmt(payment.getAmount().multiply(multiplier), payment.getCurrency().getId(),
                    strCurrencyTo, conversionDate, payment.getClient().getId(), payment.getOrganization().getId());
        } else if (payment.isPaymentComplete()) {
            return BigDecimal.ZERO;
        } else if (payment.getSettlementCancelled() != null
                && payment.getSettlementCancelled().getProcessed().equals("Y")) {

            boolean paymentCompletelyPaid = true;
            for (DebtPayment cancelledPayment : payment.getSettlementCancelled()
                    .getFinancialMgmtDebtPaymentSettlementCancelledList()) {
                if (!cancelledPayment.isPaymentComplete()
                        && cancelledPayment.getAmount().compareTo(cancelledPayment.getWriteoffAmount()) != 0
                        && getMigratedPaymentStatus(cancelledPayment).equals("NOTMIGRATED")) {
                    // write off amount is equals to the payment's amount it is considered as paid
                    paymentCompletelyPaid = false;
                    break;
                } else if (getMigratedPaymentStatus(cancelledPayment).equals("NOTPAID")) {
                    paymentCompletelyPaid = false;
                    break;
                }
            }
            if (paymentCompletelyPaid) {
                // The sum of all canceled not paid payments in the settlement is zero. This means that the
                // payment has been paid completely, as it was canceled with some other pending payments
                // (for example, the ones comming from a credit memo)
                return BigDecimal.ZERO;
            }
            List<DebtPayment> generatedPayments = payment.getSettlementCancelled()
                    .getFinancialMgmtDebtPaymentCSettlementGenerateIDList();
            if (generatedPayments == null || generatedPayments.size() == 0) {
                return BigDecimal.ZERO;
            }
            BigDecimal generatedPaymentTotalAmount = BigDecimal.ZERO;
            BigDecimal generatedPaymentOverdueAmount = BigDecimal.ZERO;
            for (DebtPayment generatedPayment : generatedPayments) {
                BigDecimal signMultiplier = generatedPayment.isReceipt() == payment.isReceipt() ? BigDecimal.ONE
                        : BigDecimal.ONE.negate();
                generatedPaymentTotalAmount = generatedPaymentTotalAmount
                        .add(getConvertedAmt(generatedPayment.getAmount(), generatedPayment.getCurrency().getId(),
                                strCurrencyTo, conversionDate, generatedPayment.getClient().getId(),
                                generatedPayment.getOrganization().getId()).multiply(signMultiplier));
                if (generatedPayment.isPaymentComplete()) {
                    continue;
                }
                generatedPaymentOverdueAmount = generatedPaymentOverdueAmount
                        .add(calculateOverdueAmount(generatedPayment, strCurrencyTo,
                                generatedPayment.getSettlementGenerate().getAccountingDate(), BigDecimal.ONE)
                                        .multiply(signMultiplier));
            }
            if (generatedPaymentTotalAmount.compareTo(BigDecimal.ZERO) == 0) {
                return BigDecimal.ZERO;
            }
            // payment amount * (generatedPaymentOverdueAmount / generatedPaymentTotalAmount)
            BigDecimal overdueAmountTmp = payment.getAmount().multiply(generatedPaymentOverdueAmount)
                    .divide(generatedPaymentTotalAmount, BigDecimal.ROUND_HALF_UP);
            // set scale of the currency using standard precision
            overdueAmount = overdueAmount.add(overdueAmountTmp
                    .setScale(payment.getCurrency().getStandardPrecision().intValue(), RoundingMode.HALF_UP));
        }
        return overdueAmount;
    }

    public static BigDecimal getConvertedAmt(BigDecimal Amt, String CurFrom_ID, String CurTo_ID, Date ConvDate,
            String client, String org) {
        if (CurFrom_ID == null || CurTo_ID == null || CurFrom_ID.equals(CurTo_ID))
            return Amt;
        ConnectionProvider conn = new DalConnectionProvider(false);

        String dateFormat = OBPropertiesProvider.getInstance().getOpenbravoProperties()
                .getProperty("dateFormat.java");
        SimpleDateFormat dateFormater = new SimpleDateFormat(dateFormat);
        String strConvertedAmount = AcctServer.getConvertedAmt(Amt.toString(), CurFrom_ID, CurTo_ID,
                dateFormater.format(ConvDate).toString(), "S", client, org, conn);
        return new BigDecimal(strConvertedAmount);
    }

    private static String getMigratedPaymentStatus(DebtPayment payment) {
        String status = "NOTMIGRATED";

        if (payment.getEntity().hasProperty("aPRMTPayment")) {
            final FIN_Payment migratedPayment = (FIN_Payment) payment.get("aPRMTPayment");
            if (migratedPayment != null) {
                if (FIN_Utility.isPaymentConfirmed(migratedPayment.getStatus(), null)) {
                    status = "PAID";
                } else {
                    status = "NOTPAID";
                }
            }
        }
        return status;
    }
}