Versionen im Vergleich

Schlüssel

  • Diese Zeile wurde hinzugefügt.
  • Diese Zeile wurde entfernt.
  • Formatierung wurde geändert.

...

More about the graded checking procedure that is implemented by default is in section 2 can be found.

Codeblock
languagejava
titleorg.nuclet.camt.rule.CheckBankTransactionRef
linenumberstrue
collapsetrue
package org.nuclet.camt.rule;
 

import java.util.ArrayList;  
import java.math.BigDecimal; 
import java.util.Calendar; 
import java.util.Collections; 
import java.util.Date;
import java.util.GregorianCalendar; 
import java.util.List; 

import org.nuclos.api.annotation.Rule;
import org.nuclos.api.businessobject.BusinessObject;
import org.nuclos.api.context.RuleContext;
import org.nuclos.api.context.UpdateContext;
import org.nuclos.api.exception.BusinessException;
import org.nuclos.api.provider.BusinessObjectProvider;
import org.nuclos.api.provider.QueryProvider;
import org.nuclos.api.provider.StatemodelProvider; 
import org.nuclos.api.rule.UpdateFinalRule;
import org.nuclos.api.statemodel.State;

import org.nuclet.common.rule.AbstractRule;   

import org.nuclet.camt.BankTransaction;
import org.nuclet.camt.BankTransactionRef;
import org.nuclet.camt.CreditDebitIndicator;
import org.nuclet.camt.comparator.BankTransactionRefComparator;
import org.nuclet.camt.facade.AbstractReferenceFacade;
import org.nuclet.camt.facade.ReferenceFacadeFactory;
import org.nuclet.camt.logic.CAMT054Logic;
import org.nuclet.camt.statemodel.ReferenceStatemodel;
import org.nuclet.camt.wrapper.AbstractConditionsOfPaymentWrapper;
import org.nuclet.camt.wrapper.AbstractReferenceWrapper;
 
/** 
 * @name CheckBankTransactionRef   
 * @description Checks if the changes done to the given bank transaction should result in subsequent changes on its references
 * @usage       
 * @change  
 * 
 * 
 * @version 1.0
 * @date 18.02.2015
 * @nuclet org.nuclet.CAMT
 * @nucletversion 1.0.0
 * @sincenucletversion 1.0.0
 * @since 18.02.2015
 * @author frank.lehmann@nuclos.de
 * 
 */
@Rule(name="CheckBankTransactionRef", description="Checks if the changes done to the given bank transaction should result in subsequent changes on its references")
public class CheckBankTransactionRef extends AbstractRule implements UpdateFinalRule 
{
    private static final BigDecimal BGD_ONEHUNDRED = new BigDecimal("100.0");
    
    // facades
    protected AbstractReferenceFacade referenceFacade = null;
    
    // private and protected values
    private List<State> lstSourceStates = null;
    private State stateDestinationState = null;
    
    
    public void initialize(RuleContext context) throws BusinessException
    {
        super.initialize(context);
        
        this.referenceFacade = ReferenceFacadeFactory.getInstance();
        
        if (this.referenceFacade == null) {
            throw new BusinessException("Method Instance() in org.nuclet.mt940.facade.ReferenceFacadeFactory does not return a CurrencyFacade instance (940.472.001)!");
        }
        
        this.lstSourceStates = referenceFacade.getSourceStates(ReferenceStatemodel.StateChange.PaymentReceived);
        this.stateDestinationState = referenceFacade.getDestinationState(ReferenceStatemodel.StateChange.PaymentReceived);
        
        if (this.lstSourceStates == null || lstSourceStates.size() == 0) {
            throw new BusinessException("No source states defined in \"" + referenceFacade.getClass() 
                + "\" for ReferenceStatemodel.StateChange.PaymentReceived (CMT.473.001)!");            
        }
        
        if (this.stateDestinationState == null) {
            throw new BusinessException("No destination state defined in \"" + referenceFacade.getClass() 
                + "\" for ReferenceStatemodel.StateChange.PaymentReceived (CMT.473.002)!");
        }
    }
    
    public void updateFinal(UpdateContext context) throws BusinessException 
    {
        initialize(context);
        
        checkReferences(context);                
    }
    
    /**
     * Check, if the changes done to the given bank transaction should result in further
     * changes and/or state changes of the references <code>BusinessObject</code>
     * 
     * @param context the current context
     * 
     * @throws BusinessException, in case an error or exception occurs
     */
    private void checkReferences(UpdateContext context) throws BusinessException
    {
        final BankTransaction boBankTransaction = context.getBusinessObject(BankTransaction.class);
        final List<BankTransactionRef> lstReferences = boBankTransaction.getBankTransactionRef();
         
        for (final BankTransactionRef ref : lstReferences) {
            final Long lngReferenceId = ref.getReferenceId(); 
            final AbstractReferenceWrapper reference = referenceFacade.getById(lngReferenceId);            
            final List<Integer> lstSourceStateNumbers = new ArrayList<Integer>();
                
            for (final State state : lstSourceStates) {
                lstSourceStateNumbers.add(Integer.valueOf(state.getNumeral()));
            }
                 
            if (lstSourceStateNumbers.contains(reference.getNuclosStateNumber())) {    
                Date datPaymentDate = checkFirstPriorityConditions(boBankTransaction, reference);
                        
                if (datPaymentDate == null) {
                    datPaymentDate = checkSecondAndThirdPriorityConditions(reference);
                } 
        
                if (datPaymentDate != null) {
                    final State stateDestinationState = referenceFacade.getDestinationState(ReferenceStatemodel.StateChange.PaymentReceived);
                            
                    reference.setPaymentDate(datPaymentDate);
                    BusinessObjectProvider.update((BusinessObject)reference.getBusinessObject());
                    StatemodelProvider.changeState(reference.getBusinessObject(), stateDestinationState);                                            
                }                                
            }
        }
    }
    
    /**
     * Checks, if the first priority conditions have been fulfilled, i.e.
     * 
     * 1a. the reference is marked as "accept first incoming payment" 
     * 
     * and
     * 
     * 1b. an incoming payment has been assigned
     *
     * @param boBankTransaction A <code>BusinessObject</code> of type <code>BankTransaction</code>
     * @param reference An object of type <code>AbstractReferenceWrapper</code>, encapuslating the
     * reference object (client billing, invoice, etc.)
     * 
     * @return The payment date, if the reference is marked as "accept first incoming payment" and 
     * an incoming payment has been assigned
     * 
     */
    private Date checkFirstPriorityConditions(final BankTransaction boBankTransaction, final AbstractReferenceWrapper reference)
    {        
        final Long lngCreditDebitIndicatorId = boBankTransaction.getCreditDebitIndId();
        final CreditDebitIndicator boCreditDebitIndicator = QueryProvider.getById(CreditDebitIndicator.class, lngCreditDebitIndicatorId);

        if (boCreditDebitIndicator.getSign().intValue() > 0 && reference.getAcceptFirstIncomingPayment()) {
            return boBankTransaction.getBookingDate();
        } else {
            return null;
        }
    }
    
    /**
     * Checks, if the second or third priority conditions have been fulfilled, i.e.
     * 
     * 2. the reference's total amount has been balanced by incoming payments
     * 
     * or
     * 
     * 3. the cash discount conditions are met
     *
     * @param reference An object of type <code>AbstractReferenceWrapper</code>, encapuslating the
     * reference object (client billing, invoice, etc.)
     * 
     * @return The payment date, if the second or third priority conditions have been fulfilled, i.e.
     * 
     * @throws BusinessException 940.472.001
     */
    private Date checkSecondAndThirdPriorityConditions(final AbstractReferenceWrapper reference) throws BusinessException
    {        
        final List<BankTransactionRef> lstBankTransactionRef = reference.getBankTransactionRef();
        final AbstractConditionsOfPaymentWrapper conditionsOfPayment = reference.getConditionsOfPayment();
        Calendar calCashDiscountLimit = null;
        Calendar calExtendedCashDiscountLimit = null;
        BigDecimal bgdTotalAmountDiscounted = BigDecimal.ZERO;
        BigDecimal bgdExtendedTotalAmountDiscounted = BigDecimal.ZERO;
        
        if (conditionsOfPayment != null && conditionsOfPayment.getCashDiscount() != null) {
            // Calculate ...
            // - the discounted amount to be payed and
            // - the time limit for cash discounts, 
            //
            // ...in case a cash discount is defined in the conditions of payment...
            //
            bgdTotalAmountDiscounted = reference.getTotalAmountGross().subtract(
                    reference.getTotalAmountGross().multiply(conditionsOfPayment.getCashDiscount()).divide(BGD_ONEHUNDRED, 10, BigDecimal.ROUND_HALF_UP)
                );
                
            if (conditionsOfPayment.getCashDiscountPeriod() != null) {
                calCashDiscountLimit = new GregorianCalendar();
                calCashDiscountLimit.setTime(reference.getDateOfInvoice());
                calCashDiscountLimit.add(Calendar.DAY_OF_YEAR, conditionsOfPayment.getCashDiscountPeriod());
                
                if (conditionsOfPayment.getCashDiscountExGratiaDays() != null
                    && conditionsOfPayment.getCashDiscountExGratiaDays().intValue() > 0) {
                    calCashDiscountLimit.add(Calendar.DAY_OF_YEAR, conditionsOfPayment.getCashDiscountExGratiaDays());
                }
            }
            
            if (conditionsOfPayment.getExtendedCashDiscount() != null) {
                // If an extended cash discount is also given, calculate those values for the extended period too...
                
                if (conditionsOfPayment.getExtendedCashDiscountPeriod() != null) {
                    calExtendedCashDiscountLimit = new GregorianCalendar();
                    calExtendedCashDiscountLimit.setTime(reference.getDateOfInvoice());
                    calExtendedCashDiscountLimit.add(Calendar.DAY_OF_YEAR, conditionsOfPayment.getExtendedCashDiscountPeriod());

                    if (conditionsOfPayment.getCashDiscountExGratiaDays() != null
                        && conditionsOfPayment.getCashDiscountExGratiaDays().intValue() > 0) {
                        calCashDiscountLimit.add(Calendar.DAY_OF_YEAR, conditionsOfPayment.getCashDiscountExGratiaDays());
                    }
                }

                bgdExtendedTotalAmountDiscounted = reference.getTotalAmountGross().subtract(
                    reference.getTotalAmountGross().multiply(conditionsOfPayment.getExtendedCashDiscount()).divide(BGD_ONEHUNDRED, 10, BigDecimal.ROUND_HALF_UP)
                );
            }
        }
                
        if (lstBankTransactionRef != null) {
            Collections.sort(lstBankTransactionRef, new BankTransactionRefComparator());
        
            Date datPaymentDate = null;                               
            Date datDiscountedPaymentDate = null;
            Date datExtendedDiscountedPaymentDate = null;
            boolean bHasReferenceAmountBeenBalanced = false;
            boolean bHasDiscountedReferenceAmountBeenBalanced = false;
            boolean bHasExtendedDiscountedReferenceAmountBeenBalanced = false;
            BigDecimal bgdTotalPaymentAmount = BigDecimal.ZERO;
                        
            for (final BankTransactionRef boBankTransactionRef : lstBankTransactionRef) {                 
                final Long lngOtherBankTransactionId = boBankTransactionRef.getBankTransactionId();
                final BankTransaction boOtherBankTransaction = QueryProvider.getById(BankTransaction.class, lngOtherBankTransactionId);
                final Long lngOtherCreditDebitIndicatorId = boOtherBankTransaction.getCreditDebitIndId();
                final CreditDebitIndicator boOtherCreditDebitIndicator = QueryProvider.getById(CreditDebitIndicator.class, lngOtherCreditDebitIndicatorId);                                       
                 
                if (boOtherCreditDebitIndicator.getSign().intValue() > 0) {
                     bgdTotalPaymentAmount = bgdTotalPaymentAmount.add(boOtherBankTransaction.getAmount());
    
                     if (!bHasReferenceAmountBeenBalanced && 
                         bgdTotalPaymentAmount.doubleValue() >= reference.getTotalAmountGross().doubleValue()) {
                         bHasReferenceAmountBeenBalanced = true;
                         datPaymentDate = boOtherBankTransaction.getBookingDate();
                     }
                
                     if (!bHasDiscountedReferenceAmountBeenBalanced && 
                         !BigDecimal.ZERO.equals(bgdTotalPaymentAmount) &&
                         bgdTotalPaymentAmount.doubleValue() >= bgdTotalPaymentAmount.doubleValue()) {
                         bHasDiscountedReferenceAmountBeenBalanced = true;
                         datDiscountedPaymentDate = boOtherBankTransaction.getBookingDate();
                     }

                     if (!bHasExtendedDiscountedReferenceAmountBeenBalanced && 
                         !BigDecimal.ZERO.equals(bgdTotalPaymentAmount) &&
                         bgdTotalPaymentAmount.doubleValue() >= bgdTotalPaymentAmount.doubleValue()) {
                         bHasExtendedDiscountedReferenceAmountBeenBalanced = true;
                         datExtendedDiscountedPaymentDate = boOtherBankTransaction.getBookingDate();
                     }
                } else {
                     bgdTotalPaymentAmount = bgdTotalPaymentAmount.subtract(boOtherBankTransaction.getAmount());
    
                     if (bHasReferenceAmountBeenBalanced && 
                         bgdTotalPaymentAmount.doubleValue() < reference.getTotalAmountGross().doubleValue()) {
                         bHasReferenceAmountBeenBalanced = false;
                         datPaymentDate = null;
                      }

                     if (bHasDiscountedReferenceAmountBeenBalanced && 
                         !BigDecimal.ZERO.equals(bgdTotalPaymentAmount) &&
                         bgdTotalPaymentAmount.doubleValue() < bgdTotalPaymentAmount.doubleValue()) {
                         bHasDiscountedReferenceAmountBeenBalanced = false;
                         datDiscountedPaymentDate = null;
                     }

                    if (bHasExtendedDiscountedReferenceAmountBeenBalanced && 
                         !BigDecimal.ZERO.equals(bgdTotalPaymentAmount) &&
                         bgdTotalPaymentAmount.doubleValue() < bgdTotalPaymentAmount.doubleValue()) {
                         bHasExtendedDiscountedReferenceAmountBeenBalanced = false;
                         datExtendedDiscountedPaymentDate = null;
                     }
                }
            }

            if (bgdTotalPaymentAmount.doubleValue() >= reference.getTotalAmountGross().doubleValue()) {
               return datPaymentDate;
            } else if (bgdTotalPaymentAmount.doubleValue() < reference.getTotalAmountGross().doubleValue()
                       && datDiscountedPaymentDate != null && calCashDiscountLimit != null
                       && datDiscountedPaymentDate.before(calCashDiscountLimit.getTime())) {
                return datDiscountedPaymentDate;
            } else if (bgdTotalPaymentAmount.doubleValue() < reference.getTotalAmountGross().doubleValue()
                       && datExtendedDiscountedPaymentDate != null && calExtendedCashDiscountLimit != null
                       && datExtendedDiscountedPaymentDate.before(calExtendedCashDiscountLimit.getTime())) {
                return datExtendedDiscountedPaymentDate;                
            } else {
                return null;
            }
        } else {
            return null;
        }        
    }
}

...