Ejemplo de proyecto de migraciĆ³n de datos

Un ejemplo de migraciĆ³n de datos

AnƔlisis de las MFI y sus datos de origen.

La MFI tiene ~ 100 oficinas (~ 70 son sucursales) y desea migrar 5 de estas sucursales a mifos.

La MFI tiene x cantidad de personal, de los cuales y son oficiales de crƩdito, y z son otros miembros del personal, como el ingreso de datos, el gerente, etc.

MFI tiene 1 producto de prƩstamo (un prƩstamo individual aplicable a clientes, 1-24 cuotas, cuotas semanales)

No hay centros como tales.

ĀæNĆŗmero de grupos por rama?

ĀæNĆŗmero de clientes por grupo?

Grupo con muchos clientes.

Clientes con prƩstamos individuales y cuentas de ahorro.

Campos personalizados para informaciĆ³n del cliente

Se toma la decisiĆ³n de ingresar manualmente el personal, las oficinas, los datos de referencia (propĆ³sitos del prĆ©stamo),

Se toma la decisiĆ³n de utilizar un enfoque de "balance de apertura". BĆ”sicamente para una sucursal y un oficial de campo especĆ­ficos, si ese oficial de campo se estĆ” reuniendo con un grupo especial el lunes. Una vez que termina el dĆ­a, se captura una hoja de cĆ”lculo con todos los detalles del prĆ©stamo para cada miembro cliente del grupo y se realiza un seguimiento de los siguientes detalles:

Monto del prƩstamo original
no de cuotas
Fecha de desembolso
Primera fecha de pago
Fecha de entrega actual
Monto pagado hasta la fecha (Principio + InterƩs)
Ciclo de prestamo
PropĆ³sito del prestamo

ExtracciĆ³n, transformaciĆ³n y carga de datos.

Esta informaciĆ³n luego se extrae de la hoja de cĆ”lculo de la plantilla y (posiblemente se transforma de alguna manera) y se carga en mifos.

En este punto, se considera que este grupo estĆ” en mifos y, a partir de ahora, deberĆ­an utilizar la aplicaciĆ³n mifos.

Pros

ĀæConsolidaciĆ³n? ĀæPregunto a ryan de nuevo?

Contras

La historia pasada de los prƩstamos no se captura.

Pasos para conseguir la configuraciĆ³n

Crear esquema base con datos base

Desde un esquema de mifos en blanco:

  • aplicar base-schema.sql
  • aplicar base-data.sql
  • Actualizar la contraseƱa de usuario 'admin' a 'testmifos'
update personnel set password=0x22648ca42330a561964dbe32f54e6a04a49d03f203ca64b2515338d9 where personnel_id=1;

Utilizar archivos de configuraciĆ³n personalizados.

DespuĆ©s de hacer un anĆ”lisis en el mfi, puede ser posible juntar los archivos de configuraciĆ³n de la aplicaciĆ³n:

  • editeĀ applicationConfiguration.custom.propertiesĀ y colĆ³quelo en el directorio de configuraciĆ³n, e.g. MIFOS_CONF
  • crear mifosBeanConfig.custom.xmlĀ (creo que esto debe ir en classpath del servidor de aplicaciones (carpeta lib por ejemplo))
  • crear mifosChartOfAccounts.custom.xmlĀ y colĆ³quelo en el directorio de configuraciĆ³n, e.g. MIFOS_CONF

AplicaciĆ³n de inicio

En este punto, deberĆ­a poder iniciar la aplicaciĆ³n mifos contra el esquema de mifos. Como resultado, la base de datos en la actualidad tiene la siguiente informaciĆ³n:

  1. ƚltima estructura de la base de datos (tablas, relaciones, restricciones, etc.)
  2. Datos de referencia que salen de la caja y deben existir para que los mifos se inicien
  3. Persistencia de alguna configuraciĆ³n de applicationConfiguration.custom.properties que ahora no se puede cambiar.

Dato de referencia

La ejecuciĆ³n de la siguiente consulta le mostrarĆ” los datos de referencia existentes

SELECT l.lookup_id, le.entity_name, l.lookup_name, le.description
FROM lookup_value l
INNER JOIN lookup_entity le
ON l.entity_id=le.entity_id
order by l.entity_id, l.lookup_id;

Datos de referencia de semillas

Los datos de referencia se rellenan aplicando base-data.sql y deben existir para que la aplicaciĆ³n funcione.

Data Type

entity_id

Options

ClientStatus

1

Pending Approval, active, on hold, cancelled, closed

GroupStatus

2

Partial, Pending, active, on hold, cancelled, closed

AccountStates

5

partial, pending, approved, disbursed to LO, active-good-standing, active-bad-standing, closed-obligations-met, closed-written-off, closed-rescheduled, cancelled

PovertyStatus

10

poor, very poor, non poor

Gender

16

male, female

PersonnelLevels

30

loan officer, non loan officer

SpouseFather

52

spouse, father, mother, child

CustomerStatus

53

active, inactive

PersonnelStatus

56

active, inactive

Language

74

English, Spanish, French, etc

LivingStatus

92

Together, Not Together

Datos de referencia personalizados

Datos de referencia que son opcionales y generalmente diferentes en un cliente por cliente

Data Type

entity_id

Options

Salutation

15

Mr., Mrs.

MaritalStatus

17

single, married, seperated, widow

Citizenship

18

Roman Catholic,Protestant Baptist Pentecostal,Born Again Christian,Seventh Day Adventist,Iglesia Ni Kristo,Jehovahs Witness,Latter Day Saints,Islam,Others

Ethinicity

19

Yes, No

EducationLevel

20

Elementary, High School, College, Vocational, None

BusinessActivities

21

BuyAndSell, Vending, SariSariStore, Retailing, Dressmaking, Garments, Handicrafts, FoodProcessing, SoapMaking, PerfumeMaking, DishwashingDetergentMaking, BeadsAccessoriesMaking, Tailoring, Upholstery, Vulcanizing, DoormatMaking, TricycleOperator

PersonnelTitles

29

Program Officer, Program Unit Supervisor, Branch Accountant, Branch Accountant Assistant, Branch Manager

NOTA:Ā La ciudadanĆ­a se usa para rastrear la religiĆ³n.
NOTA: ĀæLa etinicidad se usa para rastrear?

You should restart the application after inserting in custom reference data as lookup values are cached on start up.

Script SQL para insertar en datos de referencia especĆ­ficos del cliente

-- Entity: Salutation
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2000, 15, 'Salutation-Mr'),
(2001, 15, 'Salutation-Mrs');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2000,1, 2000,'Mr'),
(2001,1, 2001,'Mrs');

-- Entity: MaritalStatus
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2002, 17, 'MaritalStatus-Single'),
(2003, 17, 'MaritalStatus-Married'),
(2004, 17, 'MaritalStatus-Seperated'),
(2005, 17, 'MaritalStatus-Widow');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2002, 1, 2002, 'Single'),
(2003, 1, 2003, 'Married'),
(2004, 1, 2004, 'Seperated'),
(2005, 1, 2005, 'Widow');

-- Entity: Citizenship
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2006, 18, 'Citizenship-RomanCatholic'),
(2007, 18, 'Citizenship-ProtestantBaptistPentecostal'),
(2008, 18, 'Citizenship-BornAgainChristian'),
(2009, 18, 'Citizenship-SeventhDayAdventist'),
(2010, 18, 'Citizenship-IglesiaNiKristo'),
(2011, 18, 'Citizenship-JehovahsWitness'),
(2012, 18, 'Citizenship-LatterDaySaints'),
(2013, 18, 'Citizenship-Islam'),
(2014, 18, 'Citizenship-Others');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2006, 1, 2006, 'Roman Catholic'),
(2007, 1, 2007, 'Protestant Baptist Pentecostal'),
(2008, 1, 2008, 'Born Again Christian'),
(2009, 1, 2009, 'Seventh Day Adventist'),
(2010, 1, 2010, 'Iglesia Ni Kristo'),
(2011, 1, 2011, 'Jehovahs Witness'),
(2012, 1, 2012, 'Latter Day Saints'),
(2013, 1, 2013, 'Islam'),
(2014, 1, 2014, 'Others');

-- Entity: Ethinicity
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2015, 19, 'Ethinicity-Yes'),
(2016, 19, 'Ethinicity-No');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2015, 1, 2015, 'Yes'),
(2016, 1, 2016, 'No');

-- Entity: EducationLevel
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2017, 20, 'EducationLevel-Elementary'),
(2018, 20, 'EducationLevel-High School'),
(2019, 20, 'EducationLevel-College'),
(2020, 20, 'EducationLevel-Vocational'),
(2021, 20, 'EducationLevel-None');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2017, 1, 2017, 'Elementary'),
(2018, 1, 2018, 'High School'),
(2019, 1, 2019, 'College'),
(2020, 1, 2020, 'Vocational'),
(2021, 1, 2021, 'None');

-- Entity: PersonnelTitles
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2022, 29, 'PersonnelTitles-ProgramOfficer'),
(2023, 29, 'PersonnelTitles-ProgramUnitSupervisor'),
(2024, 29, 'PersonnelTitles-BranchAccountant'),
(2025, 29, 'PersonnelTitles-BranchAccountantAssistant'),
(2026, 29, 'PersonnelTitles-BranchManager');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2022, 1, 2022, 'Program Officer'),
(2023, 1, 2023, 'Program Unit Supervisor'),
(2024, 1, 2024, 'Branch Accountant'),
(2025, 1, 2025, 'Branch Accountant Assistant'),
(2026, 1, 2026, 'Branch Manager');

-- Entity: BusinessActivities
insert into lookup_value(lookup_id,entity_id,lookup_name) values
(2027, 21, 'BusinessActivities-BuyAndSell'),
(2028, 21, 'BusinessActivities-Vending'),
(2029, 21, 'BusinessActivities-SariSariStore'),
(2030, 21, 'BusinessActivities-Retailing'),
(2031, 21, 'BusinessActivities-Dressmaking'),
(2032, 21, 'BusinessActivities-Garments'),
(2033, 21, 'BusinessActivities-Handicrafts'),
(2034, 21, 'BusinessActivities-FoodProcessing'),
(2035, 21, 'BusinessActivities-SoapMaking'),
(2036, 21, 'BusinessActivities-PerfumeMaking'),
(2037, 21, 'BusinessActivities-DishwashingDetergentMaking'),
(2038, 21, 'BusinessActivities-BeadsAccessoriesMaking'),
(2039, 21, 'BusinessActivities-Tailoring'),
(2040, 21, 'BusinessActivities-Upholstery'),
(2041, 21, 'BusinessActivities-Vulcanizing'),
(2042, 21, 'BusinessActivities-DoormatMaking'),
(2043, 21, 'BusinessActivities-TricycleOperator');

insert into lookup_value_locale(lookup_value_id,locale_id,lookup_id,lookup_value) values
(2027, 1, 2027, 'Buy And Sell'),
(2028, 1, 2028, 'Vending'),
(2029, 1, 2029, 'Sari Sari Store'),
(2030, 1, 2030, 'Retailing'),
(2031, 1, 2031, 'Dressmaking'),
(2032, 1, 2032, 'Garments'),
(2033, 1, 2033, 'Handicrafts'),
(2034, 1, 2034, 'Food Processing'),
(2035, 1, 2035, 'Soap Making'),
(2036, 1, 2036, 'Perfume Making'),
(2037, 1, 2037, 'Dishwashing Detergent Making'),
(2038, 1, 2038, 'Beads Accessories Making'),
(2039, 1, 2039, 'Tailoring'),
(2040, 1, 2040, 'Upholstery'),
(2041, 1, 2041, 'Vulcanizing'),
(2042, 1, 2042, 'Doormat Making'),
(2043, 1, 2043, 'Tricycle Operator');

Roles y Permisos

  • AplicaciĆ³n relanzada con todos los datos de referencia como se muestra arriba.
  • Se crearon manualmente cinco funciones (Contador de sucursal, Asistente de contador de sucursal, Gerente de sucursal, Oficial de programas, Supervisor de unidad de programas)

Modelo de laĀ OrganizaciĆ³n

DespuĆ©s de asegurar la configuraciĆ³n, los datos de referencia se configuran correctamente para la aplicaciĆ³n, es hora de agregar elementos organizativos que son fundamentales para el funcionamiento de la aplicaciĆ³n mifos.

Modelo de jerarquĆ­a de oficinas y oficinas.

  • Hay ~ 100 oficinas, de las cuales ~ 70 son sucursales, por lo que existen otros tipos de oficinas. Se utiliza una jerarquĆ­a de oficinas de la oficina central -> Oficina regional -> Oficina de Ć”rea -> Sucursal (oficina de la divisiĆ³n)
  • Cree manualmente las primeras 11 oficinas: Oficina Central de Clientes, LuzĆ³n, Norte de LuzĆ³n, LuzĆ³n Central, Capas, NCR, NCR Norte, Tandang Sora, Bulacan, Meycauayan, Valenzuela, de las cuales 4 eran sucursales de Capas, Tandang Sora, Meycauayan, Valenzuela.

NOTA:Ā Solo creĆ© los primeros 11 hasta Valenzuela, ya que quiero migrar los datos de esta rama a mifos.

Modelo de Personal / Personal / Usuarios de la AplicaciĆ³n

  • Los primeros datos que se migrarĆ”n son para un grupo especĆ­fico de oficial de prĆ©stamos de sucursal, por lo que creo manualmente un Personal como oficial de prĆ©stamos y me asocio a la sucursal de Valenzuela.

Modelo de Productos Financieros

  • Hay un producto de prĆ©stamo general disponible, asĆ­ que producto de prĆ©stamo creado manualmente.
  • No tenĆ­a mucha informaciĆ³n sobre el producto de ahorro, por lo que se creĆ³ manualmente el producto de ahorro volunatry.

Migrar informaciĆ³n de grupo

Be Careful

Manually migrating group data cannot be done correctly without modifying the system date where the application is running or by somehow modifying the data directly on the database after the group has being created and activated.

Support Creation of Groups whoose activation date is in the past

Build flexibility into mifos services and API to allow groups to be created and activated with an activation date in the past.

CĆ³digo de ejemplo para usar la API para migrar el grupo (teniendo en cuenta la fecha de activaciĆ³n / mfiJoining en el pasado)

package demo.migration;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifos.application.admin.servicefacade.AdminServiceFacade;
import org.mifos.application.admin.servicefacade.OfficeServiceFacade;
import org.mifos.application.admin.servicefacade.PersonnelServiceFacade;
import org.mifos.application.master.business.MifosCurrency;
import org.mifos.application.meeting.util.helpers.MeetingType;
import org.mifos.application.meeting.util.helpers.RecurrenceType;
import org.mifos.application.servicefacade.GroupServiceFacade;
import org.mifos.application.servicefacade.SavingsServiceFacade;
import org.mifos.calendar.DayOfWeek;
import org.mifos.customers.util.helpers.CustomerStatus;
import org.mifos.dto.domain.AddressDto;
import org.mifos.dto.domain.ApplicableAccountFeeDto;
import org.mifos.dto.domain.GroupCreationDetail;
import org.mifos.dto.domain.MeetingDetailsDto;
import org.mifos.dto.domain.MeetingDto;
import org.mifos.dto.domain.MeetingRecurrenceDto;
import org.mifos.dto.domain.MeetingTypeDto;
import org.mifos.dto.screen.ProductDisplayDto;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.mifos.framework.util.helpers.Money;
import org.mifos.security.AuthenticationAuthorizationServiceFacade;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KMBIMigrationDemo {

	public static void main(String[] args) {

		System.setProperty("mifos.mode", "main");

		String[] configLocations = new String[2];
		configLocations[0] = "classpath:/org/mifos/config/resources/applicationContext.xml";
		configLocations[1] = "classpath:META-INF/spring/QuestionnaireContext.xml";

		// NOTE: Questionaire is coupled with applicationContext due to
		// QuestionaireMigration effort.
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(configLocations);

		// NOTE: need to ensure hibernateUtil is initialised
		StaticHibernateUtil.initialize();

		// NOTE: need to set default currency
		final MifosCurrency RUPEE = new MifosCurrency((short) 2, "RUPEE", BigDecimal.valueOf(1.0), "INR");
		Money.setDefaultCurrency(RUPEE);

		System.out.println("fetching service");
		GroupServiceFacade groupServiceFacade = applicationContext.getBean(GroupServiceFacade.class);
		AuthenticationAuthorizationServiceFacade authenticationAuthorizationServiceFacade = applicationContext.getBean(AuthenticationAuthorizationServiceFacade.class);
		System.out.println("found");

		// authenticate first of all
		authenticationAuthorizationServiceFacade.reloadUserDetailsForSecurityContext("mifos");

		String displayName =  "VAL B-211";
		Short loanOfficerId = Short.valueOf("2"); // hardcoded id of ALDRIN HONDANTE
		Short officeId = Short.valueOf("11"); // hardcoded office id of Valenzuela
		Short customerStatus = CustomerStatus.GROUP_ACTIVE.getValue();
		boolean trained = true;
		DateTime trainedOn = new DateTime().withDate(2010, 11, 30);
		DateTime mfiJoiningDate = new DateTime().withDate(2010, 12, 06);
		DateTime activationDate = new DateTime().withDate(2010, 12, 06);

		GroupCreationDetail groupCreationDetail = createGroupDto(displayName,
				loanOfficerId, officeId, customerStatus, trained, trainedOn,
				mfiJoiningDate, activationDate);

		LocalDate meetingStartDate = new LocalDate(new DateTime().withDate(2010, 12, 06));
		Integer dayOfWeek = DayOfWeek.monday();
		Integer recurrenceTypeId = RecurrenceType.WEEKLY.getValue().intValue();
		Integer every = Integer.valueOf(1);

		MeetingDto meeting = createMeetingDto(meetingStartDate, dayOfWeek,
				recurrenceTypeId, every);

		// create group (
		groupServiceFacade.createNewGroup(groupCreationDetail, meeting);
	}

	private static MeetingDto createMeetingDto(LocalDate meetingStartDate,
			Integer dayOfWeek, Integer recurrenceTypeId, Integer every) {
		String meetingPlace = "SANTULAN MALABON CITY";
		MeetingTypeDto meetingType = new MeetingTypeDto(MeetingType.CUSTOMER_MEETING.getValue().intValue(), "group meeting", "some description of meeting");
		String recurrenceName = "weekly";
		Integer dayNumber = Integer.valueOf(0);
		Integer weekOfMonth = null;

		MeetingRecurrenceDto recurrenceDetails = new MeetingRecurrenceDto(dayNumber, weekOfMonth, dayOfWeek);
		MeetingDetailsDto meetingDetailsDto = new MeetingDetailsDto(recurrenceTypeId, recurrenceName, every, recurrenceDetails);
		MeetingDto meeting = new MeetingDto(meetingStartDate, meetingPlace, meetingType, meetingDetailsDto);
		return meeting;
	}

	private static GroupCreationDetail createGroupDto(String displayName,
			Short loanOfficerId, Short officeId, Short customerStatus,
			boolean trained, DateTime trainedOn, DateTime mfiJoiningDate,
			DateTime activationDate) {
		String externalId = null;
		AddressDto addressDto = null;
		List<ApplicableAccountFeeDto> feesToApply = new ArrayList<ApplicableAccountFeeDto>();
		String parentSystemId = null;

		GroupCreationDetail groupCreationDetail = new GroupCreationDetail(displayName, externalId, addressDto,
				loanOfficerId, feesToApply, customerStatus,
				trained, trainedOn, parentSystemId, officeId,
				mfiJoiningDate, activationDate);
		return groupCreationDetail;
	}
}

Resultados de la migraciĆ³n del grupo utilizando la API (teniendo en cuenta la fecha de activaciĆ³n / mfiJoining en el pasado)

La reuniĆ³n se crea para cada lunes, semanalmente.

En la tabla de clientes, la entrada para grupo tiene los siguientes detalles de interƩs:

display name

trained

trained_date

created_date

created_by

mfijoining_date

customer_activation_date

VAL B-211

YES

30-11-2010

19-01-2011

1

06-Dec-2010

06-Dec-2010

En la tabla de programaciĆ³n de clientes, se crean diez programaciones de clientes desde el 06 de diciembre de 2010 hasta el 14 de febrero de 2011.

Be Careful

At present, only ten customer schedules are created when customer is activated and each night a batch job checks to see if more should be added. If the activation date is further than 10 of meeting periods away from today then there won't be a customer schedule existing for a meeting that should occur today or in the future until a batch job runs after midnight. So we should also check to see if customer activation date is in past and if so, create customer schedules from that date up to todays date, and then also create the 10 extra customer schedules for future meeting dates.

Migrar miembros de clientes de informaciĆ³n de grupo

Be Careful

Manually migrating client data cannot be done correctly without modifying the system date where the application is running or by somehow modifying the data directly on the database after the group has being created and activated.

Support Creation of Clients whoose activation date is in the past

Build flexibility into mifos services and API to allow groups to be created and activated with an activation date in the past.

Ejemplo de migraciĆ³n de informaciĆ³n del cliente.

package demo.migration;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifos.application.admin.servicefacade.AdminServiceFacade;
import org.mifos.application.admin.servicefacade.OfficeServiceFacade;
import org.mifos.application.admin.servicefacade.PersonnelServiceFacade;
import org.mifos.application.master.business.MifosCurrency;
import org.mifos.application.meeting.util.helpers.MeetingType;
import org.mifos.application.meeting.util.helpers.RecurrenceType;
import org.mifos.application.servicefacade.ClientServiceFacade;
import org.mifos.application.servicefacade.GroupServiceFacade;
import org.mifos.application.servicefacade.SavingsServiceFacade;
import org.mifos.application.util.helpers.YesNoFlag;
import org.mifos.calendar.DayOfWeek;
import org.mifos.customers.client.business.NameType;
import org.mifos.customers.util.helpers.CustomerStatus;
import org.mifos.dto.domain.AddressDto;
import org.mifos.dto.domain.ApplicableAccountFeeDto;
import org.mifos.dto.domain.ClientCreationDetail;
import org.mifos.dto.domain.GroupCreationDetail;
import org.mifos.dto.domain.MeetingDetailsDto;
import org.mifos.dto.domain.MeetingDto;
import org.mifos.dto.domain.MeetingRecurrenceDto;
import org.mifos.dto.domain.MeetingTypeDto;
import org.mifos.dto.domain.SavingsDetailDto;
import org.mifos.dto.screen.ClientFamilyDetailDto;
import org.mifos.dto.screen.ClientNameDetailDto;
import org.mifos.dto.screen.ClientPersonalDetailDto;
import org.mifos.dto.screen.ProductDisplayDto;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.mifos.framework.util.helpers.Money;
import org.mifos.security.AuthenticationAuthorizationServiceFacade;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KMBIMigrationDemo {

	public static void main(String[] args) {

		System.setProperty("mifos.mode", "main");

		String[] configLocations = new String[2];
		configLocations[0] = "classpath:/org/mifos/config/resources/applicationContext.xml";
		configLocations[1] = "classpath:META-INF/spring/QuestionnaireContext.xml";

		// NOTE: Questionaire is coupled with applicationContext due to
		// QuestionaireMigration effort.
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(configLocations);

		// NOTE: need to ensure hibernateUtil is initialised
		StaticHibernateUtil.initialize();

		// NOTE: need to set default currency
		final MifosCurrency RUPEE = new MifosCurrency((short) 2, "RUPEE", BigDecimal.valueOf(1.0), "INR");
		Money.setDefaultCurrency(RUPEE);

		System.out.println("fetching service");
		ClientServiceFacade clientServiceFacade = applicationContext.getBean(ClientServiceFacade.class);
		AuthenticationAuthorizationServiceFacade authenticationAuthorizationServiceFacade = applicationContext.getBean(AuthenticationAuthorizationServiceFacade.class);
		System.out.println("found");

		// authenticate first of all
		authenticationAuthorizationServiceFacade.reloadUserDetailsForSecurityContext("mifos");

		List<Short> selectedSavingProducts = new ArrayList<Short>();

		String clientName = "CARMELITA DAGALLA ALCARAZ";
		Short clientStatus = CustomerStatus.CLIENT_ACTIVE.getValue();

		boolean trained = true;
		Date trainedOn = new DateTime().withDate(2010, 11, 30).toDate();
		Date mfiJoiningDate = new DateTime().withDate(2010, 12, 06).toDate();
		LocalDate activationDate = new LocalDate(mfiJoiningDate);

		String externalId = null;
		AddressDto address = new AddressDto("48M. SANTOS ST. SANTULAN", null, null, "MALABON CITY", null, "PHILIPPINES", "1470", null);
		Short formedBy = null;
		Date dateOfBirth = new DateTime().withDate(1954, 5, 14).toDate();
		String governmentId = null;

		Short groupFlag = YesNoFlag.YES.getValue();
		Integer salutation = Integer.valueOf(2001); //Mrs. see custom reference-data for salutations
		String firstName = "CARMELITA";
		String middleName = "DAGALLA";
		String lastName = "ALCARAZ";
		String secondLastName = null;
		ClientNameDetailDto clientNameDetailDto = new ClientNameDetailDto(NameType.CLIENT.getValue(), salutation, firstName, middleName, lastName, secondLastName);

		Integer ethinicity = Integer.valueOf(19); // no
		Integer citizenship = Integer.valueOf(2006); // roman catholic
		Integer handicapped = null;
		Integer businessActivities = Integer.valueOf(2029); // sari sari
		Integer maritalStatus = Integer.valueOf(2005); // widow
		Integer educationLevel = Integer.valueOf(2018); // high school
		Short numChildren = Short.valueOf("1");
		Short gender = Short.valueOf("50"); // female
		Short povertyStatus = null;

		ClientPersonalDetailDto clientPersonalDetailDto = new ClientPersonalDetailDto(ethinicity, citizenship, handicapped,
				businessActivities, maritalStatus, educationLevel, numChildren, gender, povertyStatus);

		ClientNameDetailDto spouseFatherName = null;
		InputStream picture = null;
		List<ApplicableAccountFeeDto> feesToApply = new ArrayList<ApplicableAccountFeeDto>();
		String parentGroupId = "5";
		List<ClientNameDetailDto> familyNames = new ArrayList<ClientNameDetailDto>();
		List<ClientFamilyDetailDto> familyDetails = new ArrayList<ClientFamilyDetailDto>();
		Short loanOfficerId = null; // 2 inherit from parent
		Short officeId = null; // 11 inherit from parent

		ClientCreationDetail client = new ClientCreationDetail(selectedSavingProducts, clientName, clientStatus, mfiJoiningDate, externalId,
				address, formedBy, dateOfBirth, governmentId, trained, trainedOn, groupFlag,
				clientNameDetailDto, clientPersonalDetailDto, spouseFatherName, picture,
				feesToApply, parentGroupId, familyNames, familyDetails, loanOfficerId, officeId, activationDate);

		MeetingDto meeting = null; // will inherit meeting of parent group.
		List<SavingsDetailDto> savings = new ArrayList<SavingsDetailDto>();

		clientServiceFacade.createNewClient(client, meeting, savings);
	}
}

Resultados de la migraciĆ³n del cliente utilizando la API (teniendo en cuenta la fecha de activaciĆ³n / mfiJoining en el pasado)

La reuniĆ³n se crea para cada lunes, semanalmente.

En la tabla de clientes, la entrada para el cliente tiene los siguientes detalles de interƩs:

display name

trained

trained_date

created_date

created_by

mfijoining_date

customer_activation_date

CARMELITA DAGALLA ALCARAZ

YES

30-11-2010

19-01-2011

1

06-Dec-2010

06-Dec-2010

En la tabla de programaciĆ³n de clientes, se crean diez programaciones de clientes desde el 06 de diciembre de 2010 hasta el 14 de febrero de 2011.

Be Careful

At present, only ten customer schedules are created when customer is activated and each night a batch job checks to see if more should be added. If the activation date is further than 10 of meeting periods away from today then there won't be a customer schedule existing for a meeting that should occur today or in the future until a batch job runs after midnight. So we should also check to see if customer activation date is in past and if so, create customer schedules from that date up to todays date, and then also create the 10 extra customer schedules for future meeting dates.

Migrar los prƩstamos utilizando el enfoque de saldo de apertura

Migre los ahorros utilizando el enfoque de saldo de apertura