Buen día, tengo la solicitud de un cliente que necesita imprimir una boleta de vacaciones antes de solicitar las vacaciones en el portal, esta boleta necesita tener la distribución de las vacaciones en los períodos abiertos segun la lógica interna de Evolution, por lo tanto necesito saber como realiza la distribución Evolution para hacer el sp del reporte y para que al final tanto el reporte como la distribución de los días segun la solicitud sean iguales, por ejemplo:

Empleado va a solicitar 15 días de vacaciones distribuidos en 3 períodos que es lo que Evolution va a calcular y distribuir al final de la autorización de la solicitud de vacaciones. Entonces antes de hacer la solictud, el empleado necesita un reporte con los períodos y los días a descontar en cada período según la lógica que hará Evolution en la solicitud posteriormente.

Necesitaria la lógica exacta de Evolution para poder trasladarla al SP del reporte o si tienen el SP que me puedan comptartir se los agradecería.

Tengo la versión 1.10.1.0 de Evolution.

asked 28 Jun '17, 12:14

William%20Guevara's gravatar image

William Guevara
(suspended)
accept rate: 20%


No tenemos un diagrama o documentación de la lógica "exacta", ni tampoco se realiza en ningún SP.

Te puedo copiar el texto de la aplicación de los días de vacación a los períodos, que es lo más exacto que te puedo dar.

/// <summary>
/// Finaliza la entidad
/// </summary>
/// <param name="entity">Entidad a finalizar</param>
/// <remarks>
///     - Crea los registros de detalle de fondo de vacación asociados a los períodos que 
///       correspondan, comenzando por el mas antiguo
///     - Actualiza las columnas de días gozados de los períodos a los que se asociaron los 
///       dias de vacación
/// </remarks>
/// <returns>Resultado de validacion al actualizar la entidad</returns>
public override ValidationResults FinalizaProcesamientoEntidad(EntityObject entity)
{
    var solicitud = (SolicitudVacacion)entity;
    solicitud.Estado = EstadoAccion.Autorizado;
    solicitud.FechaCambioEstado = DateTime.Now;

    var permiteDiasConDecimal = _parametroAplicacionService.GetEsquemaValorParametro<bool>(solicitud.Empleo.Codigo, "Vacacion", NombreParametroVacacionPermiteDiasConDecimales, solicitud.Empleo.Plaza.Compania.Pais.Codigo, null, null, null);

    var horasPorDia = _parametroAplicacionService.GetEsquemaValorParametro<int>(solicitud.Empleo.Codigo, "Vacacion", NombreParametroVacacionHorasDia, solicitud.Empleo.Plaza.Compania.Pais.Codigo, null, null, null);

    if (horasPorDia <= 0)
    {
        horasPorDia = 8;
        _loggingService.Error(Str.Acciones.SolicitudVacacion.MensajeValorParametroVacacionHorasDiaMenorOIgualQueCero.GetLocalized());
    }

    var permiteSaldoNegativo = _parametroAplicacionService.GetEsquemaValorParametro<bool>(solicitud.Empleo.Codigo, "Vacacion", NombreParametroVacacionPermiteSaldoNegativo, null, solicitud.Empleo.Plaza.CentroTrabajo.Codigo, null, null);

    var diasPorAsignar = solicitud.DiasSolicitados + solicitud.HorasSolicitadas / horasPorDia;
    var fechaInicioGoce = solicitud.FechaInicio;
    var fondosVacacion = solicitud.Empleo.FondosVacacion;

    // variables para controlar que no quede en un loop infinito
    var numeroIteraciones = 0;
    var maxNumeroIteraciones = 10;
    decimal diasPorAsignarIteracionAnterior = diasPorAsignar;

    while (diasPorAsignar > 0)
    {
        // Prevencion de loop infinito
        if (diasPorAsignar == diasPorAsignarIteracionAnterior)
            numeroIteraciones++;
        else
        {
            numeroIteraciones = 1;
            diasPorAsignarIteracionAnterior = diasPorAsignar;
        }

        // Determina el período inicial donde se procesarán los días
        var periodosPorAsignar = fondosVacacion.Where(s => !s.PeriodoCerrado)
                                     .OrderBy(s => s.Orden)
                                     .ThenBy(f => f.FechaInicio)
                                     .Select(f => new { FondoVacacion = f, Saldo = (f.DiasPeriodosAnteriores + f.HorasPeriodoAnterior / (decimal)horasPorDia) + f.Dias - (f.DiasGozados + f.HorasGozadas / (decimal)horasPorDia) })
                                     .ToList();

        // Cuando se permiten saldos negativos, si no encontramos periodos con saldo, hay que usar el que tiene saldo cero mas nuevo
        var periodoSaldoCeroMasNuevo = periodosPorAsignar.LastOrDefault(x => x.Saldo == 0);
        var periodoPorAsignar = periodosPorAsignar.Count(x => x.Saldo != 0) > 0
                                    ? periodosPorAsignar.First(x => x.Saldo != 0).FondoVacacion
                                    : permiteSaldoNegativo
                                          ? periodoSaldoCeroMasNuevo != null
                                                ? periodoSaldoCeroMasNuevo.FondoVacacion
                                                : null
                                          : null;
        if (periodoPorAsignar == null)
        {
            var msg = Str.Acciones.SolicitudVacacion.MensajeNoHayPeriodosParaAsignarDiasGozados.GetLocalized().FormatWith(diasPorAsignar);
            throw new InvalidOperationException(msg);
        }

        decimal diasDescontarDePeriodo;
        decimal horasDescontarDePeriodo;

        if (diasPorAsignar > periodoPorAsignar.Saldo + periodoPorAsignar.HorasSaldo / horasPorDia && (!permiteSaldoNegativo || periodoPorAsignar != null && periodoPorAsignar.Saldo > 0))
        {
            if ((periodoPorAsignar.Saldo + periodoPorAsignar.HorasSaldo / horasPorDia) == 0)
            {
                // Vamos a chequear si hay un problema de datos porque si en este punto el saldo es cero, no podemos procesar la solicitud
                throw new AseinfoException("No se puede procesar la solicitud de vacación pues no permite saldo negativo y el período al que se asignarán los datos no tiene saldo. Si ve este mensaje, es muy probable que los datos de los períodos estén incorrectos. Revise en la tabla de fondos de vacación que el saldo coincida con la operación de descontar los días otorgados menos los días gozados (incluyendo horas si ese fuera el caso)");
            }

            diasDescontarDePeriodo = periodoPorAsignar.Saldo;
            horasDescontarDePeriodo = periodoPorAsignar.HorasSaldo;
        }
        else
        {
            diasDescontarDePeriodo = permiteDiasConDecimal ? diasPorAsignar : (int)Math.Floor(diasPorAsignar);
            horasDescontarDePeriodo = permiteDiasConDecimal ? 0 : (int)Math.Round((diasPorAsignar - diasDescontarDePeriodo) * horasPorDia, 0);
        }

        if (diasPorAsignar > 0 && diasPorAsignar < 1 && diasDescontarDePeriodo == 0 && horasDescontarDePeriodo == 0)
            throw new AseinfoException($"No se puede procesar la solicitud de vacación, porque faltan {diasPorAsignar} dias por procesar y el período al que se le asignarán reporta disponibilidad de cero días y/u horas. Esto puede ser causado porque el parámetro que permite soportar días con decimales NO está activo y los datos en el fondo de vacación o en la solicitud, tienen valores con decimales.");

        // Validación para detener un posible loop infinito
        if (numeroIteraciones > maxNumeroIteraciones && diasPorAsignar == diasPorAsignarIteracionAnterior)
        {
            throw new AseinfoException($"No se puede procesar la solicitud de vacación, porque faltan {diasPorAsignar} días por procesar y no se puede aplicar en los períodos disponibles, a pesar que pareciera existir saldo disponible ({periodoPorAsignar.Saldo} días y {periodoPorAsignar.HorasSaldo} horas).  Favor revise que los parámetros de digitación de horas, decimales y soporte para saldos negativos, están congruentes con los datos almacenados en los períodos de vacación y en la solicitud que se está procesando.");
        }

        var fechaFinalGoce = _tiempoService.GetFechaFinalPeriodoGoceVacacion(
            solicitud.Empleo,
            fechaInicioGoce,
            diasDescontarDePeriodo);

        var dvaMismaSolicitud = periodoPorAsignar.DiasGozadosVacacion.FirstOrDefault(d => d.Solicitud == solicitud);
        if (dvaMismaSolicitud != null)
        {
            dvaMismaSolicitud.Dias += diasDescontarDePeriodo;
            dvaMismaSolicitud.Horas += horasDescontarDePeriodo;
            dvaMismaSolicitud.FechaInicial = (new[] { dvaMismaSolicitud.FechaInicial, fechaInicioGoce }).Min();
            dvaMismaSolicitud.FechaFin = (new[] { dvaMismaSolicitud.FechaFin, fechaFinalGoce }).Max();
        }
        else
        {
            var diaVacacion = new DiaVacacion
            {
                Dias = diasDescontarDePeriodo,
                Horas = horasDescontarDePeriodo,
                FechaInicial = fechaInicioGoce,
                FechaFin = fechaFinalGoce,
                Fondo = periodoPorAsignar,
                Solicitud = solicitud,
                SePagaron = solicitud.SeranPagadas
            };

            periodoPorAsignar.DiasGozadosVacacion.Add(diaVacacion);
        }

        periodoPorAsignar.HorasGozadas += horasDescontarDePeriodo;
        if (periodoPorAsignar.HorasGozadas >= horasPorDia)
        {
            var horasGozadasDias = (int)Math.Floor((periodoPorAsignar.HorasGozadas / horasPorDia));
            periodoPorAsignar.DiasGozados += horasGozadasDias;
            periodoPorAsignar.HorasGozadas -= horasGozadasDias * horasPorDia;
        }

        periodoPorAsignar.DiasGozados += diasDescontarDePeriodo;
        periodoPorAsignar.Saldo -= diasDescontarDePeriodo;

        if (horasDescontarDePeriodo > 0)
        {
            if (periodoPorAsignar.HorasSaldo < horasDescontarDePeriodo)
            {
                var horasDescontarDias = (int)Math.Floor(horasDescontarDePeriodo / horasPorDia);
                periodoPorAsignar.Saldo -= horasDescontarDias + 1;
                periodoPorAsignar.HorasSaldo = horasPorDia - ((horasDescontarDePeriodo - (horasDescontarDias * 8)) - periodoPorAsignar.HorasSaldo);
            }
            else
            {
                periodoPorAsignar.HorasSaldo -= horasDescontarDePeriodo;
            }

        }

        diasPorAsignar -= (diasDescontarDePeriodo + (horasDescontarDePeriodo / horasPorDia));

        // Asignamos la fecha inicial del siguiente período de goce (si lo hubiere)
        fechaInicioGoce = fechaFinalGoce.AddDays(1);

        // Se realiza el cierre automatico del período
        var saldoPeriodo = (periodoPorAsignar.DiasPeriodosAnteriores + (periodoPorAsignar.HorasPeriodoAnterior / horasPorDia) + periodoPorAsignar.Dias) - (periodoPorAsignar.DiasGozados + (periodoPorAsignar.HorasGozadas / horasPorDia));

        if (saldoPeriodo <= 0)
        {
            if (permiteSaldoNegativo)
            {
                var ultimoPeriodo = fondosVacacion.OrderByDescending(s => s.Orden).ThenByDescending(s => s.FechaInicio).FirstOrDefault();
                if (ultimoPeriodo != null && ultimoPeriodo.Codigo != periodoPorAsignar.Codigo)
                {
                    periodoPorAsignar.PeriodoCerrado = true;
                }
            }
            else
            {
                periodoPorAsignar.PeriodoCerrado = true;
            }
        }
    }

    return ValidationResults;
}
link

answered 07 Jul '17, 17:48

Fernando%20Paz's gravatar image

Fernando Paz ♦♦
17.3k81635
accept rate: 51%

Gracias Fernando, voy a trasladar esto a un sp y se los comparto por si alguien tiene el mismo u otro issue.

(11 Jul '17, 11:38) William Guevara William%20Guevara's gravatar image

Una solución alternativa que podes probar y proponer es (suponiendo que hay una ruta de autorización):

  • Guardar la solicitud de vacaciones (en esta fase proba validar en el sp "antes de guardar" que no permita envíar a autorizar si no lleva archivo adjunto. Para revisar si no esta envíando a autorizar yo revisaría que el campo sdv_codigo_workflow sea NULL -no recuerdo haber probado esto-)
  • Generar el reporte
  • Editar la solicitud de vacaciones y adjuntar el archivo (generado del reporte) escaneado y firmado.
  • enviar a autorizar.
link

answered 11 Jul '17, 11:24

Jimy%20Tobar's gravatar image

Jimy Tobar ♦♦
(suspended)
accept rate: 56%

edited 11 Jul '17, 11:25

Gracias Jimmy, pero no me serviría solo guardar la solicitud ya que lo que necesito es la lógica de distribución en períodos que lo hace Evolution al final de la autorización de las vacaciones.

(11 Jul '17, 11:39) William Guevara William%20Guevara's gravatar image
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Evolution en BitBucket

En este sitio puede acceder al código fuente, centro de descargas y reportar bugs, propuestas y mejoras para Evolution.

Evolution en JIRA

En este sitio puedes sugerir nueva funcionalidad para Evolution, o puedes votar por la funcionalidad ya propuesta por otros usuarios.

Tags:

×49
×2
×1

Asked: 28 Jun '17, 12:14

Seen: 774 times

Last updated: 11 Jul '17, 11:39

[Acerca de] [Preguntas Frecuentes] [Privacidad] [Soporte] [Contacto]
Copyright 2013-2018. Asesores en Informática