text:
<!DOCTYPE html>

<meta content="text/html;charset=utf-8" http-equiv="content-type"/>

<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>pymel.core.modeling.polyBevel — PyMEL 1.0.7 documentation</title>
<link href="../../../_static/nature.css" rel="stylesheet" type="text/css"/>
<link href="../../../_static/pygments.css" rel="stylesheet" type="text/css"/>

<link href="../../../index-2.html" rel="top" title="PyMEL 1.0.7 documentation"/>
<link href="../../pymel.core.modeling.html" rel="up" title="pymel.core.modeling"/>
<link href="pymel.core.modeling.polyBevel3.html" rel="next" title="pymel.core.modeling.polyBevel3"/>
<link href="pymel.core.modeling.polyAverageVertex.html" rel="prev" title="pymel.core.modeling.polyAverageVertex"/>
<link href="../../../../style/adsk.cpm.css" rel="stylesheet" type="text/css"/><meta content="expert" name="experiencelevel"/><meta content="programmer" name="audience"/><meta content="enable" name="user-comments"/><meta content="ENU" name="language"/><meta content="MAYAUL" name="product"/><meta content="2016" name="release"/><meta content="Customization" name="book"/><meta content="Maya-Tech-Docs" name="component"/><meta content="/view/MAYAUL/2016/ENU/" name="helpsystempath"/><meta content="04/03/2015" name="created"/><meta content="04/03/2015" name="modified"/><meta content="Navigation

 index

 modules |

 next |

 previous |
 PyMEL 1.0.7 documentation »
 pymel.core.modeling »

 pymel.core.modeling.polyBevel ¶

 polyBevel ( *args , **kwargs ) ¶
 Bevel edges.
 Flags:

 Long Name / Short Name
 Argument Types
 Properties

 angleTolerance / at
 float

 This flag specifies the angle beyond which additional faces may be inserted to avoid possible twisting of faces. If the bevel..." name="description"/><meta content="__PyMel_generated_functions_pymel_core_modeling_pymel_core_modeling_polyBevel_html" name="topicid"/>

Navigation

index

modules |

next |

previous |

PyMEL 1.0.7 documentation »

pymel.core.modeling »

pymel.core.modeling.polyBevel¶

<tt class="descname">polyBevel</tt><big>(</big>*args, **kwargs<big>)</big>¶

Bevel edges.

Flags:

<colgroup>
<col width="1%"></col>
<col width="61%"></col>
<col width="19%"></col>
<col width="19%"></col>
</colgroup>

Long Name / Short Name
Argument Types
Properties

<tt class="docutils literal">angleTolerance</tt> / <tt class="docutils literal">at</tt>
float

This flag specifies the angle beyond which additional faces may be inserted to avoid possible twisting of faces. If the bevel produces unwanted faces, try
increasing the angle tolerance. C: Default is 5 degrees. Q: When queried, this flag returns a double.

<tt class="docutils literal">autoFit</tt> / <tt class="docutils literal">af</tt>
bool

Computes a smooth roundness, new faces round off a smooth angle. C: Default is on. Q: When queried, this flag returns an int.

<tt class="docutils literal">caching</tt> / <tt class="docutils literal">cch</tt>
bool

Toggle caching for all attributes so that no recomputation is needed

<tt class="docutils literal">constructionHistory</tt> / <tt class="docutils literal">ch</tt>
bool

Turn the construction history on or off (where applicable). If construction history is on then the corresponding node will be inserted into the history chain for
the mesh. If construction history is off then the operation will be performed directly on the object. Note:If the object already has construction history then
this flag is ignored and the node will always be inserted into the history chain.

<tt class="docutils literal">fillNgons</tt> / <tt class="docutils literal">fn</tt>
bool

<tt class="docutils literal">fraction</tt> / <tt class="docutils literal">f</tt>
float

<tt class="docutils literal">frozen</tt> / <tt class="docutils literal">fzn</tt>
bool

<tt class="docutils literal">maya2015</tt> / <tt class="docutils literal">m15</tt>
bool

<tt class="docutils literal">mergeVertexTolerance</tt> / <tt class="docutils literal">mvt</tt>
float

<tt class="docutils literal">mergeVertices</tt> / <tt class="docutils literal">mv</tt>
bool

<tt class="docutils literal">miteringAngle</tt> / <tt class="docutils literal">ma</tt>
float

<tt class="docutils literal">name</tt> / <tt class="docutils literal">n</tt>
unicode

Give a name to the resulting node.

<tt class="docutils literal">nodeState</tt> / <tt class="docutils literal">nds</tt>
int

Defines how to evaluate the node. 0: Normal1: PassThrough2: Blocking3: Internally disabled. Will return to Normal state when enabled4: Internally disabled. Will
return to PassThrough state when enabled5: Internally disabled. Will return to Blocking state when enabledFlag can have multiple arguments, passed either as a
tuple or a list.

<tt class="docutils literal">offset</tt> / <tt class="docutils literal">o</tt>
float

This flag specifies the offset distance for the bevelling. C: Default is 0.2. Q: When queried, this flag returns a float.

<tt class="docutils literal">offsetAsFraction</tt> / <tt class="docutils literal">oaf</tt>
bool

This flag specifies whether the offset is a fraction or an absolute value. If a fraction, the offset can range between 0 and 1, where 1 is the maximum possible
offset C: Default is false. Q: When queried, this flag returns an int.

<tt class="docutils literal">roundness</tt> / <tt class="docutils literal">r</tt>
float

This flag specifies the roundness of bevel. A roundness of 0 means that all new faces are coplanar. This value is only used if the autoFit value is off. C:
Default is 0.5. Q: When queried, this flag returns a float.

<tt class="docutils literal">segments</tt> / <tt class="docutils literal">sg</tt>
int

This flag specifies the number of segments used for the bevelling. C: Default is 1. Q: When queried, this flag returns an int.

<tt class="docutils literal">smoothingAngle</tt> / <tt class="docutils literal">sa</tt>
float

<tt class="docutils literal">useLegacyBevelAlgorithm</tt> / <tt class="docutils literal">com</tt>
bool

<tt class="docutils literal">uvAssignment</tt> / <tt class="docutils literal">ua</tt>
int

<tt class="docutils literal">worldSpace</tt> / <tt class="docutils literal">ws</tt>
bool

This flags specifies the used reference. If on : the offset flag is taken in world reference. If off : the offset flag is taken in object reference (the default).
C: Default is off. Q: When queried, this flag returns an int. Common flagsCommon flags

Derived from mel command <tt class="xref py py-obj docutils literal">maya.cmds.polyBevel</tt>

Example:

import pymel.core as pm

# Replace an edge by 1 face, the width of the new face is given by the offset value.
pm.polyCube( n='plg' )
pm.polyBevel( 'plg.e[7]', offset=0.2 )
pm.delete( 'plg' )

# Replace an edge by 4 faces, the new faces are rounding a smooth angle.
pm.polyCube( n='plg' )
pm.polyBevel( 'plg.e[7]', segments=4, offset=0.4 )
pm.delete( 'plg' )

# Replace an edge by 4 faces, the new faces are rounding an angle specified by the default value of roundness (i.e 0.5).
pm.polyCube( n='plg' )
pm.polyBevel( 'plg.e[7]', segments=4, autoFit=Flase )
pm.delete( 'plg' )

Previous topic

pymel.core.modeling.polyAverageVertex

Next topic

pymel.core.modeling.polyBevel3

Core Modules

<tt class="xref">animation</tt>

<tt class="xref">effects</tt>

<tt class="xref">general</tt>

<tt class="xref">language</tt>

<tt class="xref">modeling</tt>

<tt class="xref">rendering</tt>

<tt class="xref">system</tt>

<tt class="xref">windows</tt>

Type Modules

<tt class="xref">datatypes</tt>

<tt class="xref">nodetypes</tt>

<tt class="xref">uitypes</tt>

Other Modules

<tt class="xref">plugins</tt>

<tt class="xref">mayautils</tt>

<tt class="xref">util</tt>

<tt class="xref">versions</tt>

<tt class="xref">tools</tt>

This Page

Show Source

Quick search

<form action="http://help.autodesk.com/cloudhelp/2016/ENU/Maya-Tech-Docs/PyMel/search.html" class="search" method="get"></form>
<input name="q" type="text"/>
<input type="submit" value="Go"/>
<input name="check_keywords" type="hidden" value="yes"/>
<input name="area" type="hidden" value="default"/>

    Enter search terms or a module, class or function name.

Navigation

index

modules |

next |

previous |

PyMEL 1.0.7 documentation »

pymel.core.modeling »

        © Copyright 2009, Chad Dombrova.
      Created using Sphinx 1.2.3.


text:
KungFoo
=======

![Travis-CI status](https://travis-ci.org/poseidn/KungFoo.svg?branch=master)

https://travis-ci.org/poseidn/KungFoo

redpajama_set_name: RedPajamaGithub


text:
package zx.soft.storm.dao.common;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Mybatis配置类
 *
 * @author wanggang
 *
 */
public class MybatisConfig {

	private static Logger logger = LoggerFactory.getLogger(MybatisConfig.class);

	public enum ServerEnum {
		wordcount, emotion
	}

	private static Map<ServerEnum, SqlSessionFactory> sessionFactorys = new HashMap<>();

	static {
		for (ServerEnum server : ServerEnum.values()) {
			try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");) {
				sessionFactorys.put(server, new SqlSessionFactoryBuilder().build(inputStream, server.name()));
			} catch (IOException e) {
				logger.error("MybatisConfig IOException: {}", e);
				throw new RuntimeException(e);
			}
		}
	}

	public static SqlSessionFactory getSqlSessionFactory(ServerEnum server) {
		return sessionFactorys.get(server);
	}

}


text:
<service>

        <field type="text" required="true" readonly="true">
            <name label="Name">Name</name>
        </field>
        <field type="text" required="true" readonly="true">
            <name label="Namespace">Namespace</name>
        </field>
        <field type="text">
            <name label="Version">Version</name>
        </field>
        <field type="text">
            <name label="Scopes">Scopes</name>
        </field>
        <field type="text">
            <name label="Types">Types</name>
        </field>
        <field type="text-area">
            <name label="Description">Description</name>
        </field>

        <subheading>
            <heading>Contact Type</heading><heading>Contact Name/Organization Name</heading>
        </subheading>
        <field type="option-text" maxoccurs="unbounded">
            <name label="Contact">Contact</name>
            <values>
                <value>None</value><value>Technical Owner</value><value>Business Owner</value>
            </values>
        </field>

        <field type="text">
            <name label="WSDL URL">WSDL URL</name>
        </field>
        <field type="options">
            <name label="Transport Protocols">Transport Protocols</name>
            <values>
                <value>None</value><value>HTTPS</value><value>HTTP</value><value>SMTP</value><value>TCP</value><value>XMPP</value><value>JMS</value>
            </values>
        </field>
        <field type="options">
            <name label="Message Formats">Message Formats</name>
            <values>
                <value>None</value><value>SOAP 1.1</value><value>SOAP 1.2</value><value>XML</value><value>JSON</value><value>HTTP-REST</value><value>CSV</value><value>BINARY</value>
            </values>
        </field>
        <field type="options">
            <name label="Message Exchange Patterns">Message Exchange Patterns</name>
            <values>
                <value>None</value><value>Request Response</value><value>One Way</value>
            </values>
        </field>

        <field type="options">
            <name label="Authentication Platform">Authentication Platform</name>
            <values>
                <value>None</value><value>TAM_WEBSEAL</value><value>XTS-WS TRUST</value><value>BuiltIn</value><value>WSO2 Identity Server</value>
            </values>
        </field>
        <field type="options">
            <name label="Authentication Mechanism">Authentication Mechanism</name>
            <values>
                <value>None</value><value>OpenID</value><value>InfoCard</value><value>Client Certifcates</value><value>HTTPS Basic Authentication</value><value>IP Address Filtering</value><value>WS-Security/WS-Trust Token</value><value>Others</value>
            </values>
        </field>
        <field type="options">
            <name label="Authorization Platform">Authorization Platform</name>
            <values>
                <value>None</value><value>TAM_WEBSEAL</value><value>XTS-WS TRUST</value><value>BuiltIn</value><value>WSO2 Identity Server</value>
            </values>
        </field>
        <field type="options">
            <name label="Message Integrity">Message Integrity</name>
            <values>
                <value>None</value><value>SSL</value><value>WS-Security</value><value>XML Digital Signatures</value><value>Other</value>
            </values>
        </field>
        <field type="options">
            <name label="Message Encryption">Message Encryption</name>
            <values>
                <value>None</value><value>SSL</value><value>WS-Security</value><value>XML Digital Signatures</value><value>Other</value>
            </values>
        </field>
        <field type="text-area">
            <name label="Comments">Comments</name>
        </field>

        <subheading>
            <heading>Environments</heading><heading>URL</heading>
        </subheading>
        <field type="option-text" maxoccurs="unbounded">
            <name label="Endpoint">Endpoint</name>
            <values>
                <value>None</value><value>Unknown</value><value>Dev</value><value>Test</value><value>Stag</value><value>Prod</value>
            </values>
        </field>

        <subheading>
            <heading>Document Type</heading><heading>URL</heading><heading>Comment</heading>
        </subheading>
        <field type="text">
            <name label="Document Type">Document Type</name>
        </field>
        <field type="text" url="true">
            <name label="URL">URL</name>
        </field>
        <field type="text-area">
            <name label="Document Comment">Document Comment</name>
        </field>
        <field type="text">
            <name label="Document Type1">Document Type1</name>
        </field>
        <field type="text" url="true">
            <name label="URL1">URL1</name>
        </field>
        <field type="text-area">
            <name label="Document Comment1">Document Comment1</name>
        </field>
        <field type="text">
            <name label="Document Type2">Document Type2</name>
        </field>
        <field type="text" url="true">
            <name label="URL2">URL2</name>
        </field>
        <field type="text-area">
            <name label="Document Comment2">Document Comment2</name>
        </field>

</service>


text:
package org.drools.scenariosimulation.backend.util;

import org.drools.scenariosimulation.backend.runner.ScenarioException;
import org.drools.scenariosimulation.backend.runner.model.ValueWrapper;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.drools.scenariosimulation.backend.runner.model.ValueWrapper.errorEmptyMessage;

public class ScenarioBeanUtil {

    private static final Map<String, Class<?>> primitiveMap = new HashMap<>();

    static {
        primitiveMap.put("boolean", boolean.class);
        primitiveMap.put("int", int.class);
        primitiveMap.put("long", long.class);
        primitiveMap.put("double", double.class);
        primitiveMap.put("float", float.class);
        primitiveMap.put("char", char.class);
        primitiveMap.put("byte", byte.class);
        primitiveMap.put("short", short.class);
    }

    private ScenarioBeanUtil() {
    }

    public static <T> T fillBean(String className, Map<List<String>, Object> params, ClassLoader classLoader) {
        return fillBean(errorEmptyMessage(), className, params, classLoader);
    }

    @SuppressWarnings("unchecked")
    public static <T> T fillBean(ValueWrapper<Object> initialInstance, String className, Map<List<String>, Object> params, ClassLoader classLoader) {

        T beanToFill = (T) initialInstance.orElseGet(() -> newInstance(loadClass(className, classLoader)));

        for (Map.Entry<List<String>, Object> param : params.entrySet()) {

            // direct mapping already considered
            if (param.getKey().isEmpty()) {
                continue;
            }

            try {
                fillProperty(beanToFill, param.getKey(), param.getValue());
            } catch (ReflectiveOperationException e) {
                throw new ScenarioException(new StringBuilder().append("Impossible to fill ").append(className)
                                                    .append(" with the provided properties").toString(), e);
            } catch (IllegalArgumentException e) {
                throw new ScenarioException(e.getMessage(), e);
            }
        }

        return beanToFill;
    }

    private static <T> void fillProperty(T beanToFill, List<String> steps, Object propertyValue) throws ReflectiveOperationException {
        List<String> pathToProperty = steps.subList(0, steps.size() - 1);
        String lastStep = steps.get(steps.size() - 1);

        Object currentObject = beanToFill;
        if (!pathToProperty.isEmpty()) {
            ScenarioBeanWrapper<?> scenarioBeanWrapper = navigateToObject(beanToFill, pathToProperty, true);
            currentObject = scenarioBeanWrapper.getBean();
        }

        Field last = getField(currentObject.getClass(), lastStep);
        last.setAccessible(true);
        last.set(currentObject, propertyValue);
    }

    public static ScenarioBeanWrapper<?> navigateToObject(Object rootObject, List<String> steps) {
        return navigateToObject(rootObject, steps, true);
    }

    public static ScenarioBeanWrapper<?> navigateToObject(Object rootObject, List<String> steps, boolean createIfNull) {
        Class<?> currentClass = rootObject != null ? rootObject.getClass() : null;
        Object currentObject = rootObject;

        for (String step : steps) {
            if (currentObject == null) {
                throw new ScenarioException(new StringBuilder().append("Impossible to reach field ")
                                                    .append(step).append(" because a step is not instantiated")
                                                    .toString());
            }
            Field declaredField = getField(currentClass, step);
            declaredField.setAccessible(true);
            currentClass = declaredField.getType();
            try {
                currentObject = getFieldValue(declaredField, currentObject, createIfNull);
            } catch (ReflectiveOperationException e) {
                throw new ScenarioException(new StringBuilder().append("Impossible to get or create class ")
                                                    .append(currentClass.getCanonicalName()).toString());
            }
        }

        return new ScenarioBeanWrapper<>(currentObject, currentClass);
    }

    private static Object getFieldValue(Field declaredField, Object currentObject, boolean createIfNull) throws ReflectiveOperationException {
        Object value = declaredField.get(currentObject);
        if (value == null && createIfNull) {
            value = newInstance(declaredField.getType());
            declaredField.set(currentObject, value);
        }
        return value;
    }

    private static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (ReflectiveOperationException e) {
            throw new ScenarioException(new StringBuilder().append("Class ").append(clazz.getCanonicalName())
                                                .append(" has no empty constructor").toString(), e);
        }
    }

    public static Object convertValue(String className, Object cleanValue, ClassLoader classLoader) {
        // "null" string is converted to null
        cleanValue = "null".equals(cleanValue) ? null : cleanValue;

        if (!isPrimitive(className) && cleanValue == null) {
            return null;
        }

        Class<?> clazz = loadClass(className, classLoader);

        // if it is not a String, it has to be an instance of the desired type
        if (!(cleanValue instanceof String)) {
            if (clazz.isInstance(cleanValue)) {
                return cleanValue;
            }
            throw new IllegalArgumentException(new StringBuilder().append("Object ").append(cleanValue)
                                                       .append(" is not a String or an instance of ").append(className).toString());
        }

        String value = (String) cleanValue;

        try {
            if (clazz.isAssignableFrom(String.class)) {
                return value;
            } else if (clazz.isAssignableFrom(BigDecimal.class)) {
                return parseBigDecimal(value);
            } else if (clazz.isAssignableFrom(BigInteger.class)) {
                return parseBigInteger(value);
            } else if (clazz.isAssignableFrom(Boolean.class) || clazz.isAssignableFrom(boolean.class)) {
                return parseBoolean(value);
            } else if (clazz.isAssignableFrom(Byte.class) || clazz.isAssignableFrom(byte.class)) {
                return Byte.parseByte(value);
            } else if (clazz.isAssignableFrom(Character.class) || clazz.isAssignableFrom(char.class)) {
                return parseChar(value);
            } else if (clazz.isAssignableFrom(Double.class) || clazz.isAssignableFrom(double.class)) {
                return Double.parseDouble(cleanStringForNumberParsing(value));
            } else if (clazz.isAssignableFrom(Float.class) || clazz.isAssignableFrom(float.class)) {
                return Float.parseFloat(cleanStringForNumberParsing(value));
            } else if (clazz.isAssignableFrom(Integer.class) || clazz.isAssignableFrom(int.class)) {
                return Integer.parseInt(cleanStringForNumberParsing(value));
            } else if (clazz.isAssignableFrom(LocalDate.class)) {
                return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE);
            } else if (clazz.isAssignableFrom(LocalDateTime.class)) {
                return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            } else if (clazz.isAssignableFrom(LocalTime.class)) {
                return LocalTime.parse(value, DateTimeFormatter.ISO_LOCAL_TIME);
            } else if (clazz.isAssignableFrom(Long.class) || clazz.isAssignableFrom(long.class)) {
                return Long.parseLong(cleanStringForNumberParsing(value));
            } else if (clazz.isAssignableFrom(Short.class) || clazz.isAssignableFrom(short.class)) {
                return Short.parseShort(cleanStringForNumberParsing(value));
            } else if (Enum.class.isAssignableFrom(clazz)) {
                return Enum.valueOf(((Class<? extends Enum>) clazz), value);
            }
        } catch (RuntimeException e) {
            throw new IllegalArgumentException(new StringBuilder().append("Impossible to parse '")
                                                       .append(value).append("' as ").append(className).append(" [")
                                                       .append(e.getMessage()).append("]").toString());
        }

        throw new IllegalArgumentException(new StringBuilder().append("Class ").append(className)
                                                   .append(" is not natively supported. Please use an MVEL expression" +
                                                                   " to use it.").toString());
    }

    public static String revertValue(Object cleanValue) {
        if (cleanValue == null) {
            return "null";
        }

        Class<?> clazz = cleanValue.getClass();

        if (clazz.isAssignableFrom(String.class)) {
            return String.valueOf(cleanValue);
        } else if (clazz.isAssignableFrom(BigDecimal.class)) {
            return String.valueOf(cleanValue);
        } else if (clazz.isAssignableFrom(BigInteger.class)) {
            return String.valueOf(cleanValue);
        } else if (clazz.isAssignableFrom(Boolean.class) || clazz.isAssignableFrom(boolean.class)) {
            return Boolean.toString((Boolean) cleanValue);
        } else if (clazz.isAssignableFrom(Byte.class) || clazz.isAssignableFrom(byte.class)) {
            return String.valueOf(cleanValue);
        } else if (clazz.isAssignableFrom(Character.class) || clazz.isAssignableFrom(char.class)) {
            return String.valueOf(cleanValue);
        } else if (clazz.isAssignableFrom(Double.class) || clazz.isAssignableFrom(double.class)) {
            return revertDouble((Double) cleanValue);
        } else if (clazz.isAssignableFrom(Float.class) || clazz.isAssignableFrom(float.class)) {
            return cleanValue + "f";
        } else if (clazz.isAssignableFrom(Integer.class) || clazz.isAssignableFrom(int.class)) {
            return Integer.toString((Integer) cleanValue);
        } else if (clazz.isAssignableFrom(LocalDate.class)) {
            LocalDate localDate = (LocalDate) cleanValue;
            return String.format("%04d-%02d-%02d", localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
        } else if (clazz.isAssignableFrom(LocalDateTime.class)) {
            return formatLocalDateTime((LocalDateTime) cleanValue);
        } else if (clazz.isAssignableFrom(LocalTime.class)) {
            return formatLocalTime((LocalTime) cleanValue);
        }
        else if (clazz.isAssignableFrom(Long.class) || clazz.isAssignableFrom(long.class)) {
            return Long.toString((Long) cleanValue);
        } else if (clazz.isAssignableFrom(Short.class) || clazz.isAssignableFrom(short.class)) {
            return String.valueOf(cleanValue);
              } else if (Enum.class.isAssignableFrom(clazz)) {
            return String.valueOf(cleanValue);
        } else {
            return String.valueOf(cleanValue);
        }
    }

    public static String formatLocalDateTime(LocalDateTime ldt) {
        String commonFormat = "%04d-%02d-%02dT%02d:%02d:%02d";
        String nanoFormat = commonFormat + ".%09d";
        if (ldt.getNano() == 0) {
            return String.format(commonFormat, ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth(),
                                 ldt.getHour(), ldt.getMinute(), ldt.getSecond());
        } else {
            return String.format(nanoFormat, ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth(),
                                 ldt.getHour(), ldt.getMinute(), ldt.getSecond(), ldt.getNano());
        }
    }

    public static String formatLocalTime(LocalTime lt) {
        String commonFormat = "%02d:%02d:%02d";
        String nanoFormat = commonFormat + ".%09d";
        if (lt.getNano() == 0) {
            return String.format(commonFormat, lt.getHour(), lt.getMinute(), lt.getSecond());
        } else {
            return String.format(nanoFormat, lt.getHour(), lt.getMinute(), lt.getSecond(), lt.getNano());
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> Class<T> loadClass(String className, ClassLoader classLoader) {
        if (isPrimitive(className)) {
            return (Class<T>) primitiveMap.get(className);
        }
        try {
            return (Class<T>) classLoader.loadClass(className);
        } catch (ClassNotFoundException | NullPointerException e) {
            throw new ScenarioException(new StringBuilder().append("Impossible to load class ").append(className).toString(), e);
        }
    }

    /**
     * Look for a field (public or not) with name fieldName in Class clazz and in its superclasses
     * @param clazz
     * @param fieldName
     * @return
     */
    public static Field getField(Class<?> clazz, String fieldName) {
        return internalGetField(clazz.getCanonicalName(), clazz, fieldName);
    }

    private static Field internalGetField(String canonicalClassName, Class<?> clazz, String fieldName) {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            if (clazz.getSuperclass() != null) {
                return internalGetField(canonicalClassName, clazz.getSuperclass(), fieldName);
            }
        }
        throw new ScenarioException(new StringBuilder().append("Impossible to find field with name '")
                                            .append(fieldName).append("' in class ")
                                            .append(canonicalClassName).toString());
    }

    private static boolean isPrimitive(String className) {
        return primitiveMap.containsKey(className);
    }

    private static BigDecimal parseBigDecimal(String value) {
        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
        df.setParseBigDecimal(true);
        try {
            return (BigDecimal) df.parse(value);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private static BigInteger parseBigInteger(String value) {
        return parseBigDecimal(value).toBigInteger();
    }

    private static boolean parseBoolean(String value) {
        if ("true".equalsIgnoreCase(value)) {
            return true;
        } else if ("false".equalsIgnoreCase(value)) {
            return false;
        } else {
            throw new IllegalArgumentException("Impossible to parse as boolean " + value);
        }
    }

    private static char parseChar(String value) {
        if (value == null || value.length() != 1) {
            throw new IllegalArgumentException("Impossible to transform " + value + " as char");
        }
        return value.charAt(0);
    }

    private static String cleanStringForNumberParsing(String rawValue) {
        return rawValue.replaceAll("(-)\\s*([0-9])", "$1$2");
    }

    private static String revertDouble(Double doubleValue) {
        if (Double.isInfinite(doubleValue) || Double.isNaN(doubleValue)) {
            return String.valueOf(doubleValue);
        }
        return doubleValue + "d";
    }
}


text:
module Ez
  module Settings
    class ApplicationController < Ez::Settings.config.base_controller.constantize
      protect_from_forgery with: :exception

      def view(cell_name, *args)
        render html: cell("ez/settings/#{cell_name}", *args), layout: true
      end
    end
  end
end


text:
package org.mifos.accounts.loan.business;

import static org.apache.commons.lang.math.NumberUtils.DOUBLE_ZERO;
import static org.apache.commons.lang.math.NumberUtils.SHORT_ZERO;

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

import junit.framework.Assert;

import org.junit.Test;
import org.mifos.accounts.business.AccountActionDateEntity;
import org.mifos.accounts.business.AccountBO;
import org.mifos.accounts.business.AccountFeesEntity;
import org.mifos.accounts.business.AccountPaymentEntity;
import org.mifos.accounts.business.AccountTrxnEntity;
import org.mifos.accounts.exceptions.AccountException;
import org.mifos.accounts.fees.business.FeeBO;
import org.mifos.accounts.fees.business.FeeView;
import org.mifos.accounts.fees.util.helpers.FeeCategory;
import org.mifos.accounts.fees.util.helpers.FeeFormula;
import org.mifos.accounts.fees.util.helpers.FeePayment;
import org.mifos.accounts.financial.business.GLCodeEntity;
import org.mifos.accounts.fund.business.FundBO;
import org.mifos.accounts.productdefinition.business.GracePeriodTypeEntity;
import org.mifos.accounts.productdefinition.business.LoanOfferingBO;
import org.mifos.accounts.productdefinition.business.LoanOfferingTestUtils;
import org.mifos.accounts.productdefinition.business.PrdApplicableMasterEntity;
import org.mifos.accounts.productdefinition.business.PrdStatusEntity;
import org.mifos.accounts.productdefinition.business.ProductCategoryBO;
import org.mifos.accounts.productdefinition.exceptions.ProductDefinitionException;
import org.mifos.accounts.productdefinition.util.helpers.ApplicableTo;
import org.mifos.accounts.productdefinition.util.helpers.GraceType;
import org.mifos.accounts.productdefinition.util.helpers.InterestType;
import org.mifos.accounts.productdefinition.util.helpers.PrdStatus;
import org.mifos.accounts.util.helpers.AccountActionTypes;
import org.mifos.accounts.util.helpers.AccountConstants;
import org.mifos.accounts.util.helpers.AccountState;
import org.mifos.accounts.util.helpers.PaymentData;
import org.mifos.application.master.business.InterestTypesEntity;
import org.mifos.application.meeting.MeetingTemplateImpl;
import org.mifos.application.meeting.business.MeetingBO;
import org.mifos.application.meeting.util.helpers.RecurrenceType;
import org.mifos.customers.business.CustomerBO;
import org.mifos.customers.center.CenterTemplate;
import org.mifos.customers.center.CenterTemplateImpl;
import org.mifos.customers.center.business.CenterBO;
import org.mifos.customers.center.persistence.CenterPersistence;
import org.mifos.customers.exceptions.CustomerException;
import org.mifos.customers.group.GroupTemplate;
import org.mifos.customers.group.GroupTemplateImpl;
import org.mifos.customers.group.business.GroupBO;
import org.mifos.customers.group.persistence.GroupPersistence;
import org.mifos.customers.group.util.helpers.GroupConstants;
import org.mifos.customers.office.business.OfficeBO;
import org.mifos.customers.personnel.business.PersonnelBO;
import org.mifos.customers.personnel.persistence.PersonnelPersistence;
import org.mifos.framework.MifosIntegrationTestCase;
import org.mifos.framework.TestUtils;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.exceptions.ValidationException;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.mifos.framework.persistence.TestObjectPersistence;
import org.mifos.framework.util.helpers.DateUtils;
import org.mifos.framework.util.helpers.Money;
import org.mifos.framework.util.helpers.MoneyUtils;
import org.mifos.framework.util.helpers.TestGeneralLedgerCode;
import org.mifos.framework.util.helpers.TestObjectFactory;
import org.mifos.security.util.UserContext;

public class LoanBORedoDisbursalIntegrationTest extends MifosIntegrationTestCase {

    public LoanBORedoDisbursalIntegrationTest() throws Exception {
        super();
    }

    private CenterPersistence centerPersistence;
    private GroupPersistence groupPersistence;
    private UserContext userContext;
    private CustomerBO center = null;
    private CustomerBO group = null;
    private AccountBO loanBO = null;
    private MeetingBO meeting = null;
    private FeeBO fee;

    @Override
    public void setUp() throws Exception {
        centerPersistence = new CenterPersistence();
        groupPersistence = new GroupPersistence();
        initializeStatisticsService();
        userContext = TestUtils.makeUser();
        fee = null;
    }

    @Override
    public void tearDown() throws Exception {
        // TestObjectFactory.removeObject(loanOffering);
        if (loanBO != null) {
            loanBO = (AccountBO) StaticHibernateUtil.getSessionTL().get(AccountBO.class, loanBO.getAccountId());
        }
        if (group != null) {
            group = (CustomerBO) StaticHibernateUtil.getSessionTL().get(CustomerBO.class, group.getCustomerId());
        }
        if (center != null) {
            center = (CustomerBO) StaticHibernateUtil.getSessionTL().get(CustomerBO.class, center.getCustomerId());
        }
        TestObjectFactory.cleanUp(loanBO);
        TestObjectFactory.cleanUp(group);
        TestObjectFactory.cleanUp(center);
        if (null != fee) {
            fee = (FeeBO) StaticHibernateUtil.getSessionTL().get(FeeBO.class, fee.getFeeId());
            TestObjectFactory.cleanUp(fee);
        }
        StaticHibernateUtil.closeSession();
    }

    private LoanOfferingBO createLoanOffering(UserContext userContext, MeetingBO meeting, Date loanProductStartDate)
            throws ProductDefinitionException {
        PrdApplicableMasterEntity prdApplicableMaster = new PrdApplicableMasterEntity(ApplicableTo.GROUPS);
        ProductCategoryBO productCategory = TestObjectFactory.getLoanPrdCategory();
        GracePeriodTypeEntity gracePeriodType = new GracePeriodTypeEntity(GraceType.NONE);
        InterestTypesEntity interestType = new InterestTypesEntity(InterestType.FLAT);
        GLCodeEntity glCodePrincipal = (GLCodeEntity) StaticHibernateUtil.getSessionTL().get(GLCodeEntity.class,
                TestGeneralLedgerCode.LOANS_TO_CLIENTS);
        GLCodeEntity glCodeInterest = (GLCodeEntity) StaticHibernateUtil.getSessionTL().get(GLCodeEntity.class,
                TestGeneralLedgerCode.INTEREST_ON_LOANS);

        boolean interestDeductedAtDisbursement = false;
        boolean principalDueInLastInstallment = false;
        Money loanAmount = new Money(getCurrency(), "300");
        Double interestRate = new Double(1.2);
        Short installments = new Short((short) 6);
        LoanOfferingBO loanOffering = LoanOfferingTestUtils.createInstanceForTest(userContext, "TestLoanOffering", "TLO",
                productCategory, prdApplicableMaster, loanProductStartDate, null, null, gracePeriodType, (short) 0,
                interestType, loanAmount, loanAmount, loanAmount, interestRate, interestRate, interestRate,
                installments, installments, installments, true, interestDeductedAtDisbursement,
                principalDueInLastInstallment, new ArrayList<FundBO>(), new ArrayList<FeeBO>(), meeting,
                glCodePrincipal, glCodeInterest);

        PrdStatusEntity prdStatus = new TestObjectPersistence().retrievePrdStatus(PrdStatus.LOAN_ACTIVE);
        LoanOfferingTestUtils.setStatus(loanOffering, prdStatus);
        LoanOfferingTestUtils.setGracePeriodType(loanOffering, gracePeriodType);
        loanOffering.save();

        return loanOffering;
    }

    private LoanBO redoLoanAccount(GroupBO group, LoanOfferingBO loanOffering, MeetingBO meeting,
            Date disbursementDate, List<FeeView> feeViews) throws AccountException {
        Short numberOfInstallments = Short.valueOf("6");
        List<Date> meetingDates = TestObjectFactory.getMeetingDates(meeting, numberOfInstallments);
        loanBO = LoanBO.redoLoan(TestUtils.makeUser(), loanOffering, group, AccountState.LOAN_APPROVED,
                TestUtils.createMoney("300.0"), numberOfInstallments, meetingDates.get(0), false, 1.2, (short) 0, null,
                feeViews, null, DOUBLE_ZERO, DOUBLE_ZERO, SHORT_ZERO, SHORT_ZERO, false, null);
        ((LoanBO) loanBO).save();
        new TestObjectPersistence().persist(loanBO);
        return (LoanBO) loanBO;
    }

    private void disburseLoan(UserContext userContext, LoanBO loan, Date loanDisbursalDate) throws AccountException,
            PersistenceException {
        PersonnelBO personnel = new PersonnelPersistence().getPersonnel(userContext.getId());
        loan.disburseLoan(null, loanDisbursalDate, Short.valueOf("1"), personnel, null, Short.valueOf("1"));
        new TestObjectPersistence().persist(loan);
    }

    private void applyPaymentForLoan(UserContext userContext, LoanBO loan, Date paymentDate, Money money)
            throws AccountException {
        loan.setUserContext(userContext);
        List<AccountActionDateEntity> accntActionDates = new ArrayList<AccountActionDateEntity>();
        accntActionDates.addAll(loan.getAccountActionDates());

        PaymentData paymentData = loan.createPaymentData(userContext, money, paymentDate, null, null, Short
                .valueOf("1"));
        loan.applyPaymentWithPersist(paymentData);
        new TestObjectPersistence().persist(loan);
    }

    private Date createPreviousDate(int numberOfDays) {
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, -numberOfDays);
        Date pastDate = DateUtils.getDateWithoutTimeStamp(calendar.getTime());
        return pastDate;
    }

    private LoanBO redoLoanWithMondayMeeting(UserContext userContext, Date disbursementDate, List<FeeView> feeViews)
            throws Exception {
        /*
         * OfficeTemplate template =
         * OfficeTemplateImpl.createUniqueOfficeTemplate
         * (OfficeLevel.BRANCHOFFICE); OfficeBO office =
         * getOfficePersistence().createOffice(userContext, template);
         */
        OfficeBO office = TestObjectFactory.getOffice(TestObjectFactory.SAMPLE_BRANCH_OFFICE);
        meeting = new MeetingBO(MeetingTemplateImpl.createWeeklyMeetingTemplateOnMondaysStartingFrom(disbursementDate));

        CenterTemplate centerTemplate = new CenterTemplateImpl(meeting, office.getOfficeId());
        center = getCenterPersistence().createCenter(userContext, centerTemplate);

        GroupTemplate groupTemplate = GroupTemplateImpl.createNonUniqueGroupTemplate(center.getCustomerId());

        group = createGroup(userContext, groupTemplate, disbursementDate);

        LoanOfferingBO loanOffering = createLoanOffering(userContext, meeting, disbursementDate);
        return redoLoanAccount((GroupBO) group, loanOffering, meeting, disbursementDate, feeViews);
    }

    private LoanBO redoLoanWithMeetingToday(UserContext userContext, Date disbursementDate, List<FeeView> feeViews)
            throws Exception {
        /*
         * OfficeTemplate template =
         * OfficeTemplateImpl.createUniqueOfficeTemplate
         * (OfficeLevel.BRANCHOFFICE); OfficeBO office =
         * getOfficePersistence().createOffice(userContext, template);
         */
        OfficeBO office = TestObjectFactory.getOffice(TestObjectFactory.SAMPLE_BRANCH_OFFICE);
        meeting = new MeetingBO(MeetingTemplateImpl.createWeeklyMeetingTemplateStartingFrom(disbursementDate));

        CenterTemplate centerTemplate = new CenterTemplateImpl(meeting, office.getOfficeId());
        center = getCenterPersistence().createCenter(userContext, centerTemplate);

        GroupTemplate groupTemplate = GroupTemplateImpl.createNonUniqueGroupTemplate(center.getCustomerId());

        group = createGroup(userContext, groupTemplate, disbursementDate);

        LoanOfferingBO loanOffering = createLoanOffering(userContext, meeting, disbursementDate);
        return redoLoanAccount((GroupBO) group, loanOffering, meeting, disbursementDate, feeViews);
    }

    protected LoanBO redoLoanWithMondayMeetingAndVerify(UserContext userContext, int numberOfDaysInPast,
            List<FeeView> feeViews) throws Exception {
        LoanBO loan = redoLoanWithMondayMeeting(userContext, createPreviousDate(numberOfDaysInPast), feeViews);
       Assert.assertEquals(new Money(getCurrency(), "300.0"), loan.getLoanAmount());
        return loan;
    }

    protected LoanBO redoLoanWithMeetingTodayAndVerify(UserContext userContext, int numberOfDaysInPast,
            List<FeeView> feeViews) throws Exception {
        LoanBO loan = redoLoanWithMeetingToday(userContext, createPreviousDate(numberOfDaysInPast), feeViews);
       Assert.assertEquals(new Money(getCurrency(), "300.0"), loan.getLoanAmount());
        return loan;
    }

    // inlined the persistence method to set the activation/creation date of
    // customer on or before disbursement date
    private GroupBO createGroup(UserContext userContext, GroupTemplate groupTemplate, final Date disbursementDate)
            throws PersistenceException, ValidationException, CustomerException {
        CenterBO center = null;
        if (groupTemplate.getParentCenterId() != null) {
            center = getGroupPersistence().getCenterPersistence().getCenter(groupTemplate.getParentCenterId());
            if (center == null) {
                throw new ValidationException(GroupConstants.PARENT_OFFICE_ID);
            }
        }
        GroupBO group = TestObjectFactory.createInstanceForTest(userContext, groupTemplate, center, disbursementDate);
        new GroupPersistence().saveGroup(group);
        return group;
    }

    protected LoanBO redoLoanAndVerify(UserContext userContext, Date disbursementDate, List<FeeView> feeViews)
            throws Exception {
        LoanBO loan = redoLoanWithMondayMeeting(userContext, disbursementDate, new ArrayList<FeeView>());
       Assert.assertEquals(new Money(getCurrency(), "300.0"), loan.getLoanAmount());
        return loan;
    }

    private void disburseLoanAndVerify(UserContext userContext, LoanBO loan, int numberofDaysInPast) throws Exception {
        Date disbursementDate = createPreviousDate(numberofDaysInPast);
        disburseLoan(userContext, loan, disbursementDate);
       Assert.assertEquals(disbursementDate.getTime(), loan.getDisbursementDate().getTime());

        // Validate disbursement information
        Iterator<AccountPaymentEntity> payments = loan.getAccountPayments().iterator();
        AccountPaymentEntity disbursement = payments.next();
        Iterator<AccountTrxnEntity> trxns = disbursement.getAccountTrxns().iterator();
        AccountTrxnEntity trxn;
        do {
            trxn = trxns.next();
            if (trxn.getAccountAction() == AccountActionTypes.DISBURSAL) {
                break;
            }
        } while (trxns.hasNext());
       Assert.assertEquals(AccountActionTypes.DISBURSAL, trxn.getAccountAction());
       Assert.assertEquals(loan.getLoanAmount(), trxn.getAmount());
       Assert.assertEquals(disbursementDate.getTime(), trxn.getActionDate().getTime());

    }

    private void verifyPayment(LoanBO loan, Date paymentDate, Money paymentAmount) throws Exception {

        Iterator<AccountPaymentEntity> payments = loan.getAccountPayments().iterator();
        AccountPaymentEntity payment;
        Iterator<AccountTrxnEntity> trxns = null;
        AccountTrxnEntity trxn = null;
        boolean foundThePayment = false;
        do {
            payment = payments.next();
            trxns = payment.getAccountTrxns().iterator();
            do {
                trxn = trxns.next();
                if (trxn.getAccountAction() == AccountActionTypes.LOAN_REPAYMENT
                        && trxn.getAmount().equals(paymentAmount)) {
                    foundThePayment = true;
                   Assert.assertEquals(paymentDate, trxn.getActionDate());
                    break;
                }
            } while (trxns.hasNext());
        } while (payments.hasNext());
       Assert.assertTrue("Couldnt find a LOAN_REPAYMENT", foundThePayment);
    }

    protected void applyAndVerifyPayment(UserContext userContext, LoanBO loan, int numberOfDaysInPast, Money amount)
            throws Exception {

        Date paymentDate = createPreviousDate(numberOfDaysInPast);
        applyPaymentForLoan(userContext, loan, paymentDate, amount);
        verifyPayment(loan, paymentDate, amount);

    }

    protected void removeAccountFee(LoanBO loan) throws Exception {
        for (AccountFeesEntity accountFeesEntity : loan.getAccountFees()) {
            loan.removeFees(accountFeesEntity.getFees().getFeeId(), Short.valueOf("1"));
        }
    }

    private FeeBO createOneTimeAmountFee(double amount) {
        fee = TestObjectFactory.createOneTimeAmountFee("oneTimeAmountFee", FeeCategory.GROUP, String.valueOf(amount),
                FeePayment.TIME_OF_FIRSTLOANREPAYMENT);
        return fee;
    }

    private List<FeeView> createFeeViewsWithOneTimeAmountFee(double amount) {
        List<FeeView> feeViews = new ArrayList<FeeView>();
        FeeBO upFrontAmountFee = createOneTimeAmountFee(amount);
        feeViews.add(new FeeView(userContext, upFrontAmountFee));
        return feeViews;
    }

    private FeeBO createPeriodicAmountFee(double amount) {
        fee = TestObjectFactory.createPeriodicAmountFee("PeriodicAmountFee", FeeCategory.GROUP, String.valueOf(amount),
                RecurrenceType.WEEKLY, (short) 1);
        return fee;
    }

    private List<FeeView> createFeeViewsWithPeriodicAmountFee(double amount) {
        List<FeeView> feeViews = new ArrayList<FeeView>();
        FeeBO upFrontAmountFee = createPeriodicAmountFee(amount);
        feeViews.add(new FeeView(userContext, upFrontAmountFee));
        return feeViews;
    }

    private FeeBO createPeriodicRateFee(double rate) {
        fee = TestObjectFactory.createPeriodicRateFee("PeriodicRateFee", FeeCategory.GROUP, rate, FeeFormula.AMOUNT,
                RecurrenceType.WEEKLY, (short) 1);
        return fee;
    }

    private List<FeeView> createFeeViewsWithPeriodicRateFee(double rate) {
        List<FeeView> feeViews = new ArrayList<FeeView>();
        FeeBO periodicRateFee = createPeriodicRateFee(rate);
        feeViews.add(new FeeView(userContext, periodicRateFee));
        return feeViews;
    }

    private void applyCharge(LoanBO loan, short chargeId, double chargeAmount) throws Exception {
        loan.applyCharge(chargeId, chargeAmount);
        new TestObjectPersistence().persist(loan);
    }

    @Test
    public void testRedoLoan() throws Exception {

        // long transactionCount =
        // getStatisticsService().getSuccessfulTransactionCount();

        int loanStartDaysAgo = 14;
        int paymentDaysAgo = 8;

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, loanStartDaysAgo, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, loanStartDaysAgo);

        Assert.assertFalse(loan.havePaymentsBeenMade());

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyAndVerifyPayment(userContext, loan, paymentDaysAgo, new Money(getCurrency(), "50"));

       Assert.assertTrue(loan.havePaymentsBeenMade());

        LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    @Test
    public void testRedoLoanApplyWholeMiscPenaltyBeforeRepayments() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        Double feeAmount = new Double("33.0");
       Assert.assertTrue(MoneyUtils.isRoundedAmount(feeAmount));
        applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), feeAmount);

        Assert.assertFalse(loan.havePaymentsBeenMade());

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 33.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    @Test
    public void testRedoLoanApplyWholeMiscPenaltyAfterPartialPayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), new Double("33"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 33.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    @Test
    public void testRedoLoanApplyWholeMiscPenaltyAfterFullPayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        // make one full repayment
        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), new Double("33"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 33.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    @Test
    public void testRedoLoanApplyFractionalMiscPenaltyBeforeRepayments() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), new Double("33.7"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 0.0, 33.7);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
    }

    @Test(expected = org.mifos.accounts.exceptions.AccountException.class)
    public void testRedoLoanApplyFractionalMiscPenaltyAfterPartialPayment() throws Exception {

        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            Assert.assertFalse(MoneyUtils.isRoundedAmount(33.7));
            Assert.assertFalse(loan.canApplyMiscCharge(new Money(getCurrency(), new BigDecimal(33.7))));
            // Should throw AccountExcption
            applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), new Double("33.7"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 0.0, 33.7);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanApplyFractionalMiscPenaltyAfterFullPayment() throws Exception {

        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            // make one full repayment
            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            // Should throw AccountException
            applyCharge(loan, Short.valueOf(AccountConstants.MISC_PENALTY), new Double("33.7"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 0.0, 33.7);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    @Test
    public void testRedoLoanApplyWholeMiscFeeBeforeRepayments() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        Double feeAmount = new Double("33.0");
       Assert.assertTrue(MoneyUtils.isRoundedAmount(feeAmount));
        applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), feeAmount);

        Assert.assertFalse(loan.havePaymentsBeenMade());

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 33.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    @Test
    public void testRedoLoanApplyWholeMiscFeeAfterPartialPayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), new Double("33"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 33.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyWholeMiscFeeAfterFullPayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        // make one full repayment
        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), new Double("33"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 33.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyFractionalMiscFeeBeforeRepayments() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), new Double("33.7"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 33.7, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyFractionalMiscFeeAfterPartialPayment() throws Exception {

        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            Assert.assertFalse(MoneyUtils.isRoundedAmount(33.7));
            Assert.assertFalse(loan.canApplyMiscCharge(new Money(getCurrency(), new BigDecimal(33.7))));
            // Should throw AccountExcption
            applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), new Double("33.7"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 1.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 33.7, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanApplyFractionalMiscFeeAfterFullPayment() throws Exception {

        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            // make one full repayment
            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            // Should throw AccountException
            applyCharge(loan, Short.valueOf(AccountConstants.MISC_FEES), new Double("33.7"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.2, 0.1, 0.0, 33.7, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.2, 0.8, 0.0, 0.0, 0.0);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanWithOneTimeWholeAmountFee() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithOneTimeAmountFee(10.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyOneTimeWholeAmountFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createOneTimeAmountFee(10.0).getFeeId(), 10.0);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyOneTimeWholeAmountFeeAfterRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        // make one full repayment
        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createOneTimeAmountFee(10.0).getFeeId(), 10.0);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanWithOneTimeFractionalAmountFee() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithOneTimeAmountFee(10.2));
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 61.0, 50.7, 0.1, 10.2, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.7, 0.3, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyOneTimeFractionalAmountFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createOneTimeAmountFee(10.2).getFeeId(), 10.2);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 62.0, 51.7, 0.1, 10.2, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 44.7, 1.3, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanWithOneTimeFractionalAmountFeeAfterRepayment() throws Exception {
        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

            // make one full repayment
            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            applyCharge(loan, createOneTimeAmountFee(10.2).getFeeId(), 10.2);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanWithPeriodicWholeAmountFee() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithPeriodicAmountFee(10.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 56.0, 45.5, 0.5, 10.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyPeriodicWholeAmountFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createPeriodicAmountFee(10.0).getFeeId(), 10.0);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 71.0, 50.9, 0.1, 20.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 56.0, 45.5, 0.5, 10.0, 0.0, 0.0);
    }

    public void testRedoLoanWithPeriodicWholeAmountFeeAfterRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        // make one full repayment
        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createPeriodicAmountFee(10.0).getFeeId(), 10.0);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 71.0, 50.9, 0.1, 20.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 61.0, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 56.0, 45.5, 0.5, 10.0, 0.0, 0.0);
    }

    public void testRedoLoanWithPeriodicRateFee() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithPeriodicRateFee(5.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 15.0, 0.0, 0.0);
    }

    public void testRedoLoanApplyPeriodicRateFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

        applyCharge(loan, createPeriodicRateFee(5.0).getFeeId(), 5.0);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 30.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 15.0, 0.0, 0.0);

    }

    public void testRedoLoanApplyPeriodicRateFeeAfterRepayment() throws Exception {
        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, new ArrayList<FeeView>());
            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 51.0, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 45.5, 0.5, 0.0, 0.0, 0.0);

            // make one full repayment
            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "51"));

            LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

            // Expect AccountException
            applyCharge(loan, createPeriodicRateFee(5.0).getFeeId(), 5.0);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanRemovePeriodicWholeAmountFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMeetingTodayAndVerify(userContext, 14, createFeeViewsWithPeriodicAmountFee(10.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 10.0, 0.0, 0.0);

        removeAccountFee(loan);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    public void testRedoLoanRemovePeriodicWholeAmountFeeAfterRepayment() throws Exception {

        LoanBO loan = redoLoanWithMeetingTodayAndVerify(userContext, 14, createFeeViewsWithPeriodicAmountFee(10.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 10.0, 0.0, 0.0);

        // make one full repayment
        applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "61"));

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 10.0, 0.0, 0.0);

        removeAccountFee(loan);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 0.0, 0.0, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 10.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);
    }

    /**
     * Removing a periodic amount fee, whose amount is more precise than the
     * rounding precision specified for the installment, should result in an
     * AccountException.
     * <p>
     * TODO: financial-calculation. This is a short-term solution (V1.1) until
     * it is determined how rounding should be applied when fees or charges are
     * added or removed partway through a loan cycle.
     */

    public void testRedoLoanRemovePeriodicFractionalAmountFeeBeforePayment() throws Exception {

        LoanBO loan = redoLoanWithMeetingTodayAndVerify(userContext, 14, createFeeViewsWithPeriodicAmountFee(5.1));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 46.0, 0.9, 5.1, 0.0, 0.0);

        removeAccountFee(loan);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.8, 0.1, 5.1, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.7, 1.3, 0.0, 0.0, 0.0);
    }

    /**
     * Removing a periodic amount fee, whose amount (5.1) is more precise than
     * the rounding precision specified for the installment (0), should result
     * in an AccountException.
     * <p>
     * TODO: financial-calculation. This is a short-term solution (V1.1) until
     * it is determined how rounding should be applied when fees or charges are
     * added or removed partway through a loan cycle.
     */

    public void testRedoLoanRemovePeriodicFractionalAmountFeeAfterPayment() throws Exception {
        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithPeriodicAmountFee(5.1));

            disburseLoanAndVerify(userContext, loan, 14);

            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

            // expect account exception
            removeAccountFee(loan);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    public void testRedoLoanRemovePeriodicRateFeeBeforeRepayment() throws Exception {

        LoanBO loan = redoLoanWithMeetingTodayAndVerify(userContext, 14, createFeeViewsWithPeriodicRateFee(5.0));

        disburseLoanAndVerify(userContext, loan, 14);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 15.0, 0.0, 0.0);

        removeAccountFee(loan);

        LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 15.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 0.0, 0.0, 0.0);
        LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 0.0, 0.0, 0.0);

    }

    public void testRedoLoanRemovePeriodicRateFeeAfterRepayment() throws Exception {
        try {
            LoanBO loan = redoLoanWithMondayMeetingAndVerify(userContext, 14, createFeeViewsWithPeriodicRateFee(5.0));

            disburseLoanAndVerify(userContext, loan, 14);

            LoanTestUtils.assertInstallmentDetails(loan, 1, 50.9, 0.1, 15.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 2, 50.9, 0.1, 15.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 3, 50.9, 0.1, 15.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 4, 50.9, 0.1, 15.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 5, 50.9, 0.1, 15.0, 0.0, 0.0);
            LoanTestUtils.assertInstallmentDetails(loan, 6, 45.5, 0.5, 15.0, 0.0, 0.0);

            applyAndVerifyPayment(userContext, loan, 7, new Money(getCurrency(), "50"));

            // Expect AccountException
            removeAccountFee(loan);
            Assert.fail("Expected AccountException !!");
        } catch (AccountException e) {
        }
    }

    private CenterPersistence getCenterPersistence() {
        return centerPersistence;
    }

    private GroupPersistence getGroupPersistence() {
        return groupPersistence;
    }
}


text:
import { CState } from './state';

export class Country {
  id: string;
  iso_name: string;
  name: string;
  states: CState[];
}