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:
- Última estructura de la base de datos (tablas, relaciones, restricciones, etc.)
- Datos de referencia que salen de la caja y deben existir para que los mifos se inicien
- 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"); S