====== Fusión de empresas ====== La fusión de empresas tiene como objetivo unir todos los datos relevantes de varias bases de datos de Smart en una sola base de datos principal. En grandes rasgos los pasos a seguir son estos: - Definir la empresa principal. Esta base de datos va a mantener sus datos, a las que se va añadiendo los datos de las demás empresas. - Definir el orden de las empresas secundarias. A veces en el momento de importar los datos, el orden de importación es importante. - Definir las tablas a fusionar y el tipo de cada una. - Importar los datos de las empresas secundarias a tablas temporales en la base de datos pricipal. - Definir recodificaciones de los códigos en las tablas temporales. - Crear los códigos nuevos para los datos importados en las tablas temporales. - Copiar los datos de las tablas temporales a las tablas definitivas, manteniendo las dependencias entre tablas (FKs). Los instrumentos para realizar una fusión son principalmente los dos siguientes: - El dialogo SmartFusion, al que podemos acceder con ''Ctrl+F10'' desde el dialogo //Archivo/Base de datos/Conexiones externas//. - El programa [[sat:smartversionconsole|SmartVersionConsole]], que es un programa en línea de comando, que recibe como parámetro el nombre de un fichero con los comandos a ejecutar, igual que //isql// o //SmartVersion//. Después de cada paso se puede buscar en el fichero log por las palabras ''(error )'' y ''(warning)'' (incluidos los paréntesis) para ver cualquier problema. Cuidado, la palabra error lleva dos espacios detrás. ===== Paso 1: Definir las empresas ===== Hay que definir las empresas de la fusión en la cabecera del dialogo de la fusión. {{:usu:fusionar_empresas:fusion1.jpg|Definir empresas}} Con el número de orden 0 siempre se debería poner la base de datos principal. Todas las empresas tienen que ser definidas en el dialogo de //Conexiones externas//, al que se puede acceder con ''F10'' desde //Archivo/Base de datos/Conexiones externas//. ===== Paso 2: Generar estadísticas ===== **Duración: 50 miuntos** Este paso compara todas las tablas de la empresa principal con las tablas correspondientes en las empresas secundarias, y guarda los resultados en las líneas del dialogo SmartFusion. Hay que crear un script de sql con una sola línea: FUSION_COMPARE_DBS; Después se llama a SmartVersionConsole con el nombre de este script: smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_compare_dbs.sql > fusion_compare_dbs.log Después encontramos en el dialogo las estadísticas para todas las empresas secundarias y todas las tablas de la empresa principal. {{:usu:fusionar_empresas:fusion2.jpg|Estadísticas}} Explicación de los campos del detalle del dialogo: ^Campo ^Descripción ^ |Regs. iguales en todas bds. |Si este campo contiene ''S'' entonces son iguales los registros de todas las bases de datos secundarias con los registros de la base de datos principal. | |Cero regs. en todas bds. |Si este campo contiene ''S'' entonces no hay registros en ninguna de las bases de datos secundarias. | |Se fusiona por dependencia |Si este campo contiene ''S'' entonces no se ha marcado la tabla para la fusión, pero se necesita para resolver FKs. Se actualiza este campo con ''Ctrl+F11''. | ===== Paso 3: Definir las tablas a fusionar ===== Ahora hay que seleccionar las tablas que se quiere fusionar. Para hacerlo se escoge en la cabecera una de las empresas secundarias y después se selecciona la línea con la tabla a fusionar. **Con F11 se define la fusión de la tabla actual para TODAS las empresas secundarias, y no solo para la empresa actual. El mismo efecto tiene poner manualmente ''S'' en el campo ''Fusionar''.** **La selección del menú //Calcular dependencias// (''Ctrl+F11'') tiene el efecto de que se marcan con ''S'' en el campo ''Fusionar por dependencia'' todas aquellas tablas, que no están incluidas en la fusión, pero de cuales dependen algunas tablas a fusionar por un FK. Además se define el tipo ''COMPLETAR'' para estas tablas.** {{:usu:fusionar_empresas:fusion3.jpg|Escoger tablas}} ===== Paso 4: Crear las tablas temporales ===== **Duración: 3 minutos** Ahora que sabemos las tablas de la fusión, podemos crear las tablas temporales para los datos de las empresas secundarias. Creamos un script sql con la línea FUSION_CREATE_TABS; y lo llamamos con smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_create_tabs.sql > fusion_create_tabs.log Este paso se puede repetir todas las veces necesarias, por ejemplo después de añadir más tablas de fusión en el paso 3. SmartVersionConsole, en este caso, va a comprobar la estructura de las tablas temporales que ya existen. Si se ha añadido algún campo en una actualización, SmartVersionConsole va a añadir el mismo campo a la tabla temporal correspondiente. En caso de que haya cambiado el tipo de un campo o que se haya borrado un campo, se muestra un error. ===== Paso 5: Importación de datos ===== **Duración: 35 minutos** Este paso nos pasa los registros de las empresas secundarias a las tablas temporales. Creamos un script sql con la línea FUSION_SINC_TABS; y lo ejecutamos con smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_sinc_tabs.sql > fusion_sinc_tabs.log También podemos ejecutar este paso las veces que queramos, y, claro, hay que ejecutarlo por última vez justo antes de la fusión para coger todos los datos de las empresas secundarias. En la importación de datos, SmartVersionConsole borra todos los registros, donde no hemos metido la mano para definir códigos de correspondencia (ver paso 7), y después inserta otra vez todos los registros de las empresas secundarias. Los registros cambiados manualmente, los actualiza. ===== Paso 6: Definir tipos ===== Ahora volvemos al dialogo SmartFusion para definir la manera de fusionar cada tabla. {{:usu:fusionar_empresas:fusion4.jpg|Definir tipos}} Si se deja en blanco el tipo de fusión, se usa el tipo //COMPLETAR// como valor por defecto. ==== COMPLETAR ==== Completar la tabla de destino significa, que solo pasan a la tabla definitiva los registros, cuyo código aún no existe en esta tabla. ==== RECOD ==== Este tipo sirve para recodificar el código de una tabla. Se usa un patrón para definir el valor nuevo que va a tener el código de cada registro en la tabla de destino. Se puede definir el patrón en el campo //Criterio de recodificación// del dialogo de fusión. Si no se define ningún criterio, pero asigna a la tabla el tipo //RECOD//, se usa por defecto el patrón ''MAD__#F(#*)'', donde hay que sustituir ''MAD'' por el código de instalación de donde viene el registro. En el patrón se pueden usar símbolos especiales, para definir la recodificación de cada código. ^Símbolo ^Significado ^ |#A |Este símbolo se va a reemplazar por el código alfanumérico de la empresa, definido en la cabecera del dialogo de fusión. | |#B |Si el código original contiene un guión, se reemplaza este guión por el código alfanumérico de la empresa, definido en la cabecera del dialogo de fusión. Si el código original no contiene guión, se usa el patrón restante. | |#N |Este símbolo se va a reemplazar por el código numérico de la empresa, definido en la cabecera del dialogo de fusión. | |#M |Si el código original contiene un guión, se reemplaza este guión por el código numérico de la empresa, definido en la cabecera del dialogo de fusión. Si el código original no contiene guión, se usa el patrón restante. | |#* |Este símbolo se va a reemplazar por el código original entero | |#0 |Este símbolo se va a reemplazar por el primer carácter del código original | |#1 |Este símbolo se va a reemplazar por el segundo carácter del código original | |#n |Este símbolo se va a reemplazar por el carácter (n + 1) del código original | |#F(...) |Si el código calculado es demasiado largo para caber en el campo, se corta la cadena entre los paréntesis desde el final. | |#C(...) |Igual que #F(...), solo que se corta desde el comienzo de la cadena entre los paréntesis. | Si un código calculado ya existe, se añade al final un número separado por la barra de división ('/'). Si por añadir este número el código queda demasiado largo para caber en el campo, se corta la sub-cadena denominada por los símbolos #F o #C. Ejemplos (suponemos que se trata de un código de 10 caracteres, y que el código alfanumérico de MAD sea 'D' y el numérico '2'): ^Patrón ^Código original ^Código nuevo ^Código nuevo con id. ^ |#A/#F(#*) |0123456789 |D/01234567 |D/012345/0 | |#N/#C(#*) |0123456789 |2/23456789 |2/456789/0 | |#N#0#1_#C(#2#3#4#5#6#7#8#9) |0900012345 |2090012345 |20912345/0 | Se escogería el código del campo //Código nuevo con id.// en caso de que el código del campo //Código nuevo// ya existiese. El número añadido se aumenta hasta encontrar un código inexistente. ==== RENUM ==== Este tipo sirve para códigos numéricos. Se busca en tabla de destino el valor máximo actual y va aumentando para crear código nuevos para todos los registros a insertar. Se puede definir un generador en el campo //Criterio de recodificación//, que se va a adaptar al nuevo valor máximo después de crear los códigos nuevos. ==== MANUAL ==== No se fusionan estas tablas, pero si se comprueba que todos los registros existen en la tabla de destino. ===== Paso 7: Recodificación manual ===== También es posible dar a cualquier registro un código nuevo manualmente. Para hacerlo utilizamos los campos //DBL$...//, como podemos ver en la siguiente imagen. {{:usu:fusionar_empresas:fusion5.jpg|Recodificación manual}} Miramos primero a la primera línea de la rejilla de detalle de la imagen. Allí podemos ver, que el tercero de tipo ''CL'' y código ''000190'' de la empresa MAD debería recibir el código ''STS_TST'' de la empresa MAV. Para conseguirlo hemos puesto ''MAV'' en el campo //DBL$XFUS_COD_INST//, ''CL'' en el campo //DBL$TIPO// y ''STS_TST'' en //DBL$CODIGO//. El resultado de estos ajustes se puede ver en los campos //NVO$TIPO//, //NVO$CODIGO// y //XFUS_FUSIONAR//, que se rellenan en el siguiente paso 8. En //NVO$TIPO// y //NVO$CODIGO// encontramos el código nuevo para el registro, y en //XFUS_FUSIONAR// encontramos 'S', si el código metido a mano en los campos //DBL$...// no existe en la tabla de destino, y 'N' si ya existía. La última línea del detalle nos muestra otra posibilidad que tenemos. Podemos decir que el registro coincide con otro registro, bien de la misma empresa o de otra, y por lo tanto tiene que recibir el mismo código nuevo como el registro al que se refiere. En este ejemplo, el proveedor ''100300'' de MAD y el proveedor ''000002'' de MCA coinciden y van a recibir el código nuevo ''D/000002''. (El tipo cambia a ''AC'' porque lo he mapeado así en la tabla XFUS_TIPO_TERCERO para hacer pruebas de funcionamiento.) En todos los campos //DBL$...// se puede ojear, empezando en //DBL$XFUS_COD_INST//. Si se escoge la empresa principal (''MAV''), se ojea sobre la tabla de destino (''TERCERO'') en los demás campos, si se escoge una empresa secundaria, se ojea sobre la tabla de fusión (''XFUS_TERCERO''). **IMPORTANTE: Este paso se debería hacer ya sobre la base de datos definitivo, porque trabajamos con los datos definitivos de las tablas de fusión y sería mucho trabajo pasar los ajustes de una base de datos de prueba a la definitiva.** ==== Paso 7.1: Casos especiales de la recodificación manual ==== === Paso 7.1.1: Ajustar los códigos de obra en los almacenes y direcciones de clientes === Script: Produccion 1\Fusion\ANTFUS_OBRA_TERCERO_FKS.sql Para algunos códigos de obra se han creado almacenes y direcciones de clientes con el mismo código. Hay que adaptar estos FKs virtuales aplicando el script. **El script recodifica todos los códigos de obra. Hay que revisar el script para cada fusión.** === Paso 7.1.2: Ajustar los códigos de almacén y direcciones de terceros derivados de algunos clientes === Script: Produccion 1\Fusion\ANTFUS_ALMACEN_CLIENTES.sql Hay almacenes y direcciones de tercero igual que la clave primaria de un tercero correspondiente, por ejemplo ''CL123456''. Con el script se adaptan estos códigos al nuevo código que va a tener el tercero. **OJO: El script supone que se fusionan los terceros con el tipo COMPLETAR. Hay que revisar el script para cada fusión.** === Paso 7.1.3: Activos coincidentes === Script: Produccion 1\Fusion\ANTFUS_ACTIVOS_COINCIDENTES.sql Poner correspondencias de código para los activos que coinciden en el número de serie. **Probablemente esto no sea necesario en todas las fusiones, depende del caso concreto.** Selección de los activos coincidentes: SELECT F.NRO_SERIE, F.CODIGO AS "Activo THG", F.DESCRIPCION AS "Nombre THG", F.COD_INVENTARIO AS "Producto THG", A.CODIGO AS "Activo THE", A.DESCRIPCION as "Nombre THE", A.COD_INVENTARIO AS "Producto THE" FROM XFUS_ACTIVO F LEFT JOIN ACTIVO A ON A.NRO_SERIE=F.NRO_SERIE WHERE A.CODIGO IS NOT NULL === Paso 7.1.4: Índices de FKs usados en instrucciones PLAN === Puede haber procedimientos y disparadores donde se usa un índice de una FK en la instrucción PLAN. Para poder borrar una FK con esta dependencia antes de la fusión hay que poner en comentarios dicha instrucción PLAN. - XCPA_PDTES_TERCERO_GRUPOS ===== Paso 8: Prueba de la recodificación ===== **Duración: 3 horas** En este paso hacemos una prueba de la recodificación de los registros a fusionar. El objetivo es rellenar los campos //NVO$...// de todas las tablas de fusión. Creamos un script sql con la línea FUSION_CREATE_PKS(PRUEBA); y lo ejecutamos con smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_create_pks.sql > fusion_create_pks.log Después podemos ver en el detalle del dialogo de fusión, como se han rellenado los códigos nuevos en los campos //NVO$...//. También se puede poner FUSION_CREATE_PKS(REAL); en el script. En este caso se van a adaptar también los generadores de las tablas de tipo //RENUM//. Al poner //PRUEBA// como parámetro, no se actualizarán los generadores. La prueba se puede repetir tantas veces que sea necesario. ==== Recodificación de una sola tabla ==== Para recodificar solo una tabla, se puede poner el siguiente comando en el script: FUSION_CREATE_PKS(PRUEBA,CAB_ALBARAN_VENTA); ===== Paso 9: Adaptar los FKs ===== **Duración: 1 hora** Este paso adapta todas las claves ajenas en las tablas de fusión. Hay FKs que se pueden arreglar con una sola instrucción sql, y otras donde el programa tiene que adaptar los códigos registro por registro. Este último caso sucede por ejemplos con FKs que contienen campos del PK. **NO SE PUEDE REPETIR ESTE PASO. ANTES DE REALIZAR ESTE PASO SE DEBERÍA HACER UNA COPIA DE LA BASE DE DATOS, PARA PODER IR MARCHA ATRÁS EN CASO DE CUALQUIER PROBLEMA.** Creamos un script sql con la línea FUSION_CREATE_FKS; y lo ejecutamos con smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_create_fks.sql > fusion_create_fks.log Si este paso falla para alguna tabla, lo podemos ver en el log. En este caso podemos repetir el paso solo para esta tabla con FUSION_CREATE_FKS(nombreDeLaTabla); ===== Paso 10: Fusionar ===== **Duración: 1 hora 10 minutos** Bueno, es el último paso, donde vamos a copiar los registros marcados para fusionar de las tablas de fusión a sus tablas de destino final. **NO SE PUEDE REPETIR ESTE PASO. ANTES DE REALIZAR ESTE PASO SE DEBERÍA HACER UNA COPIA DE LA BASE DE DATOS, PARA PODER IR MARCHA ATRÁS EN CASO DE CUALQUIER PROBLEMA.** Creamos el script ''fusion_run.sql'' con la línea FUSION_RUN; y lo ejecutamos con smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i fusion_run.sql > fusion_run.log **Al terminar se debería buscar en el fichero log por la palabra ''(error )'' (incluidos los paréntesis y dos espacios). De esta forma se puede ver los constraints (PKs y FKs) que no se han reinstalado bien.** ===== Paso 11: Hacer correcciones ===== ==== Paso 11.1: Corregir FK REGISTRO_MOVS.DOCUMENTO ==== Script: Produccion 1\Fusion\DESPFUS_FKS_REG_MOVS_DOCUMENTO.sql Para corregir el FK de REGISTRO_MOVS.DOCUMENTO a las facturas de venta y compra, se llama el script de la siguiente manera: firebird@servidordb:~/fusion$ /opt/firebird/bin/isql -user sysdba -pass ******** Use CONNECT or CREATE DATABASE to specify a database SQL> set names WIN1252; SQL> connect localhost:/ibdata/fusion/sssabc.gdb; Database: localhost:/ibdata/fusion/sssabc.gdb, User: sysdba SQL> output DESPFUS_FKS_REG_MOVS_DOCUMENTO.out; SQL> input DESPFUS_FKS_REG_MOVS_DOCUMENTO.sql; SQL> exit; Luego comprobamos el resultado en ''DESPFUS_FKS_REG_MOVS_DOCUMENTO.out''. ==== Paso 11.2: Corregir los códigos de producto para activos ==== Script: Produccion 1\Fusion\DESPFUS_CAMBIA_PROD_NRO_SERIE.sql Si se ha ejecutado el paso 7.1.3, es posible que existen para un mismo activo combinaciones de //nº de serie// y distinctos //códigos de producto//. Esto es el caso si el activo con el mismo número de serie tenía un código de producto en una base de datos, y otro código de producto en otra base de datos. El script adapta el código de producto para todos los activos y se llama de la siguiente manera: firebird@servidordb:~/fusion$ /opt/firebird/bin/isql -user sysdba -pass ******** Use CONNECT or CREATE DATABASE to specify a database SQL> set names WIN1252; SQL> connect localhost:/ibdata/fusion/sssabc.gdb; Database: localhost:/ibdata/fusion/sssabc.gdb, User: sysdba SQL> output DESPFUS_CAMBIA_PROD_NRO_SERIE.out; SQL> input DESPFUS_CAMBIA_PROD_NRO_SERIE.sql; SQL> exit; Luego comprobamos el resultado en ''DESPFUS_CAMBIA_PROD_NRO_SERIE.out''. ==== Paso 11.3: Quitar comentarios de instrucciones PLAN ==== Si hemos puesto comentarios en procedimientos o disparadores en el paso 7.1.4, ahora los tenemos que quitar otra vez. ==== Paso 11.4: Revisar ajustes de la empresa ==== Revisar ajustes de empresa si las empresas fusionadas estaban configuradas de forma diferente. ==== Paso 11.5: Recalcular saldos de cuentas ==== Ejecutar los procedimientos - EXECUTE PROCEDURE **ACUM_RECAL_SALDOS**; - EXECUTE PROCEDURE **ACUM_RECAL_SALDOS_CTA** '1000-01-01', '3000-12-31'; - EXECUTE PROCEDURE **AC_MI_RECAL** NULL; ==== Paso 11.x: Recodificar claves primarias ==== Con SmartVersionConsole ahora también se puede cambiar la clave primaria de cualquier tabla. Para eso se usan los tres comandos **START_RECOD(nombreTabla), RECOD(códigoAntiguo=códigoNuevo) y END_RECOD**. ^Comando ^Descripción ^Ejemplos ^ |START_RECOD(tablName) |Cada recodificación tiene que empezar con este comando. El único parámetro es el nombre de la tabla, donde se quiere recodificar la clave primaria. |START_RECOD(TERCERO); | |RECOD(códigoAntiguo=códigoNuevo) |Para cada código que se quiere cambiar, hay que poner un comando RECOD. Cada comando RECOD tiene tantos parámetros como tiene campos la clave primaria de la tabla. Cada parámetro lleva el código antiguo y el nuevo separado por el símbolo '='. |RECOD(CL=CL,000033=000035); | |END_RECOD |La recodificación de una tabla siempre tiene que terminar con este comando, que reestablece los FK y triggeres que hayan sido borrados en el START_RECOD. |END_RECOD; | **NOTAS IMPORTANTES:** - Siempre hacer una copia de la base de datos antes de hacer cualquier recodificación. Si la recodificación casca con una excepción sin terminar con el comando END_RECOD, la base de datos queda inconsistente. - No puede haber ninguna conexión abierta mientras SmartVersionConsole está realizando la recodificación. Esto es un script de ejemplo START_RECOD(ALMACEN); RECOD(ABCD=ABCC); RECOD(ABCE=ABCC); END_RECOD; START_RECOD(TERCERO); RECOD(CL=CL,000033=000035); RECOD(CL=CL,000034=000035); END_RECOD; Y se llama como siempre con (suponiendo que el script se llama //recod.sql//: smartversionconsole.exe -w -d localhost/gds_fb21:h:\Database_fb21\sssmav.gdb -i recod.sql > recod.log Si se quiere omitir los mensajes de //trace//, en lugar de la opción ''-w'' se puede usar la opción ''-v''.