﻿import React, { Fragment, memo, useState, useEffect, } from 'react';
import { useHistory, withRouter } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faReply, faSave, faSearch, faFileWord, faList, faFolderPlus, faCalculator, faClipboardList } from '@fortawesome/free-solid-svg-icons';

import { SiteRutas } from '../../../request/RutasConfig.jsx';

import Config from '../../../components/Util/constantes.js';
import { Notificacion } from '../../../components/Util/Notificacion/Notificacion.jsx';
import ModalSpinner from '../../../components/UI/modalSpinner/modalSpinner.jsx';
import BotonArriba from '../../../components/UI/botonArriba/botonArriba.jsx';
import ModalBusqueda from '../../../components/UI/modalBusqueda/modalBusqueda.jsx';
import ModalBusquedaTree from '../../../components/UI/modalBusqueda/modalBusquedaTree.jsx';

import {
    farmatearMontos, validarDecimal, Round, farmatearFechaEstandar,
    itemSelect, validarIntVig, validaCuenta, datosArbol, validaCCosto
} from '../../../components/Util/Util.jsx';
import { useSessionStorage } from '../../../components/Util/Hooks/useSessionStorage.jsx';
import Swal from 'sweetalert2';
import { Type } from 'react-bootstrap-table2-editor';
import moment from 'moment';

//Seguridad
import Session from '../../../components/Util/session/index.jsx';
import { Obtener_MenuOpciones_Lista_Request, Obtener_MenuNombre_Request } from "../../../request/MenuRequest.jsx";
import ModalSeguridad from "../../Seguridad/ModalSeguridad.jsx";
import optSeg from '../../../components/Util/seg-menu-opciones.js';

import {
    TipoAsiento_Listar_Request, EncabezadoAsiento_ObtenerContador_Request,
    DetalleAsiento_Listar_Request, EncabezadoAsiento_Guardar_Request,
    EncabezadoAsiento_ObtenerAsiento_Request, DetallePlantillas_Listar_Request, EncaPlantillas_Consultar_Request,
    EncaPlantillas_Guardar_Request, EncaPlantillas_ModificarFechaAct_Request,
    Contabilidad_ObtenerContadorAsiento_Request, EncabezadoAsiento_Modificar_Request, EncabezadoAsiento_ModificarUtilizado_Request
} from '../../../request/MantenimientosRequest.jsx';
import { Catalogo_Lista_Request, CentroCosto_Lista_CCC_Request, CentroCosto_Lista_CXCC_Request, CentroCosto_Lista_CXCCEmpresa_Request, CentroCostos_CentroDefault_Request } from '../../../request/ServicioRequest.jsx';
import { Empresa_Consulta_Request } from "../../../request/SeguridadRequest.jsx";

import MantAsientoInt from './MantAsientoInt.jsx';
import ModalPlantilla from './modalPlantilla.jsx';
import ModalBitacora from './modalBitacora.jsx';
import ModalMontoPorc from './modalMontoPorc.jsx';
import { config } from '@fortawesome/fontawesome-svg-core';

function MantAsiento(props) {
    const pDatos = {
        Tipo: { value: "", attributes: { readOnly: false, focus: false, label: 'Número', hidden: "unset" } },
        Numero: { value: "0", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        Descripcion: { value: "", attributes: { readOnly: false, focus: false, label: 'Descripción', hidden: "unset", maxLength: 510 } },
        FechaAnio: { value: "0", attributes: { readOnly: false, focus: false, label: '\u00a0', hidden: "unset" } },
        FechaMes: { value: "", attributes: { readOnly: false, focus: false, label: 'Fecha', hidden: "unset" } },
        Monto: { value: 0, attributes: { readOnly: false, focus: false, label: 'Monto', hidden: "unset" } },
        NombrePl: { value: "", attributes: { readOnly: false, focus: false, label: 'Nombre', hidden: "unset" } },
        DescripcionPl: { value: "", attributes: { readOnly: false, focus: false, label: 'Descripción', hidden: "unset", maxLength: 255 } },
        TipoPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Tipo', hidden: "unset" } },
        EstadoPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Estado', hidden: "unset" } },
        DescripcionPlCk: { value: "", attributes: { readOnly: false, focus: false, label: 'Descripción', hidden: "unset" } },
        DescripcionPl2: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset", maxLength: 255 } },
        MontosPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Montos', hidden: "unset" } },
        DocPorLineaPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Doc. por línea', hidden: "unset" } },
        DescPorLineaPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Desc. por línea', hidden: "unset" } },
        FechaPorLineaPl: { value: true, attributes: { readOnly: false, focus: false, label: 'Fecha por línea', hidden: "unset" } },
        AsientoBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Asiento', hidden: "unset" } },
        DigitadoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Digitado Por', hidden: "unset" } },
        NombreDigitadoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        AprobadoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Aprobado Por', hidden: "unset" } },
        NombreAprobadoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        AplicadoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Aplicado Por', hidden: "unset" } },
        NombreAplicadoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        AnuladoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Anulado Por', hidden: "unset" } },
        NombreAnuladoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        ModificadoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Modificado Por', hidden: "unset" } },
        NombreModificadoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        ReversadoPorBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Reversado Por', hidden: "unset" } },
        NombreReversadoBi: { value: "", attributes: { readOnly: true, focus: false, label: '\u00a0', hidden: "unset" } },
        UltimaActualizacionBi: { value: "", attributes: { readOnly: true, focus: false, label: 'Última Actualización', hidden: "unset" } },
    };
    const spinner = { mostrar: false, texto: '', tipo: 3 };
    const [Datos, setDatos] = useState(pDatos);
    const [SpinnerModal, setSpinnerModal] = useState(spinner);
    const [empresa, setEmpresa] = useSessionStorage('empresaCON');
    const [empresaNombre, setEmpresaNombre] = useSessionStorage('empresaNombreCON');
    const [datosEmpresa, setDatosEmpresa] = useState(undefined);
    const [token, setToken] = useSessionStorage('tokenCON', '');
    const [usuario, setUsuario] = useSessionStorage('usuarioCON');
    const [usuarioS, setUsuarioS] = useSessionStorage('UsuarioSCON', '');
    const [Pais, setPais] = useSessionStorage('paisCON');
    const [id, setId] = useState(0);
    const [idPlantilla, setIdPlantilla] = useState(0);
    let historyMenu = useHistory();
    const [listaDatos, setListaDatos] = useState([]);
    const [listaTipo, setListaTipo] = useState([]);
    const [selectedTipo, setSelectedTipo] = useState(undefined);
    const listaMeses = Config.listaMeses;
    const [selectedOptionMes, setSelectedOptionMes] = useState(undefined);
    const [validarBalanceado, setValidarBalanceado] = useState(false);
    const [guardarYNuevo, setGuardarYNuevo] = useState(false);
    const [plantilla, setPlantilla] = useState(null);

    //Seguridad
    const [menuId, setMenuId] = useState(0);
    const [menuOpciones, setMenuOpciones] = useState([]);
    const [showModalSeguridad, setShowModalSeguridad] = useState(false);
    const [opcionValidar, setOpcionValidar] = useState(0);
    const [opcionValidarNombre, setOpcionValidarNombre] = useState('');

    //Datos formulario
    const [selectModalTree, setSelectModalTree] = useState(false);
    const [pColumn, setPColumn] = useState(undefined);
    const [pColumnIndex, setPColumnIndex] = useState(undefined);
    const [pRow, setPRow] = useState(undefined);
    const [pRowIndex, setPRowIndex] = useState(undefined);
    const [idCtaObj, setIdCtaObj] = useState(undefined);
    const [selectModal, setSelectModal] = useState(undefined);
    const [rowsSelected, setRowSelected] = useState(undefined);
    const [listaArbolCuenta, setListaArbolCuenta] = useState([]);
    const [listCentroCosto, setListCentroCosto] = useState([]);
    const [listCentroCostoFiltro, setListCentroCostoFiltro] = useState([]);
    const [indexCost, setIndexCost] = useState(undefined);
    const [idCCObj, setIdCCObj] = useState(undefined);
    const [selectedCuenta, setSelectedCuenta] = useState(undefined);
    const [indexC, setIndexC] = useState(undefined);
    const [actTabla, setActTabla] = useState(false);
    const [filaSeleccionada, setFilaSeleccionada] = useState(undefined);
    const [listCuentasCont, setListCuentasCont] = useState([]);
    const [listCuentas, setListCuentas] = useState([]);
    const [listCCosto, setListCCosto] = useState([]);
    const [listCXCC, setListCXCC] = useState([]);
    const [selectedCentroCosto, setSelectedCentroCosto] = useState(undefined);
    const tipoCreacion = [{ id: 1, value: 'Normal' }, { id: 2, value: 'De Plantilla' }, { id: 3, value: 'De Excel' }];
    const [selectedTipoCreacion, setSelectedTipoCreacion] = useState(tipoCreacion[0]);
    const [asiento, setAsiento] = useState(undefined);
    const [totalDebe, setTotalDebe] = useState(0);
    const [totalHaber, setTotalHaber] = useState(0);
    const [selectModalPl, setSelectModalPl] = useState(false);
    const [selectModalBi, setSelectModalBi] = useState(false);
    const [selectModalMontoPorc, setSelectModalMontoPorc] = useState(false);
    const [fModificado, setFModificado] = useState(false);
    const [fEstadoAsiento, setFEstadoAsiento] = useState(Config.eaDigitado);
    const cuentaright = { textAlign: 'right', width: '10%' };
    const cuentacenter = { textAlign: 'center', width: '90%' };
    const tablest = { width: '100%' };
    const Header = [
        { title: 'Centro Costo', field: 'CentroCosto' },
        { title: 'Nombre', field: 'Nombre' },
        { title: 'id', field: 'ID', hidden: true },
    ]

    const columnas = [
        { dataField: 'llave', text: '', csvExport: false, hidden: true },
        { dataField: 'llave', text: '', csvExport: false, hidden: true },
        {
            dataField: 'CuentaStr', text: 'Cuenta', csvText: 'Cuenta', sort: true, footer: '',
            editable: true, validator: (newValue, row, column) => {
                return onValidarCuenta(newValue, row, column);
            },
            formatter: (e, column, columnIndex, row, rowIndex) => {
                const _llaveCta = column.llave;
                const campo =
                    <table style={tablest}>
                        <tbody>
                            <tr style={tablest}>
                                <td id={_llaveCta} style={cuentacenter}>{column.CuentaStr}</td>
                                <td style={cuentaright} > <a type="button" onClick={() => { handleCuentaModal(column, columnIndex, row, rowIndex) }} ><i className="fa fa-search"></i></a></td>
                            </tr>
                        </tbody>
                    </table>
                return campo;
            }
        },
        { dataField: 'NombreCuenta', text: 'Nombre de Cuenta', sort: true, editable: false, footer: '', },
        { dataField: 'Centro_Costo', text: 'Centro Costo', hidden: true, csvExport: true, sort: true, editable: false, footer: '', },
        {
            dataField: 'Centro_CostoStr', text: 'Centro Costo', csvExport: false, sort: true, editable: true, footer: '',
            validator: (newValue, row, column) => {
                return onValidarCCosto(newValue, row, column);
            },
            formatter: (e, column, columnIndex, row, rowIndex) => {
                const _llave = column.llave + 'B';
                const campo =
                    <table style={tablest}>
                        <tbody>
                            <tr style={tablest}>
                                <td id={_llave} style={cuentacenter} > {column.Centro_CostoStr} </td>
                                <td style={cuentaright} > <a type="button" onClick={() => { handleModal(column, columnIndex) }} ><i className="fa fa-search"></i></a></td>
                            </tr>
                        </tbody>
                    </table>
                return campo;
            }

        },
        {
            dataField: 'Fecha', text: 'Fecha', sort: true, editable: true, footer: '',align: 'center',
            formatter: (row, cell) => { return cell.Fecha !== '' ? farmatearFechaEstandar(cell.Fecha) : '' },
            validator: (newValue, row, column) => {
                return onValidarFecha(newValue, row, column);
            },
            editor: {
                type: Type.DATE
            }
        },
        {
            dataField: 'Documento', text: 'Documento',  classes: "ColumnText", csvText: 'Documento', editable: true, sort: true, align: 'left', footer: '',
            editor: { type: Type.TEXTAREA },
            validator: (newValue, row, column) => {
                if (newValue.length > 255) {
                    return {
                        valid: false,
                        message: '¡No puede superar los 255 caracteres!'
                    }
                } else {
                    return true;
                }
            },
        },
        {
            dataField: 'Referencia', text: 'Descripción',  classes: "ColumnText", csvText: 'Referencia', sort: true, align: 'left',
            headerAlign: 'left', editable: true, editor: { type: Type.TEXTAREA },
            validator: (newValue, row, column) => {
                if (newValue.length > 510) {
                    return {
                        valid: false,
                        message: '¡No puede superar los 510 caracteres!'
                    }
                } else {
                    return true;
                }
            },
            footerStyle: (column, colIndex) => {
                if (totalDebe - totalHaber < 0) {
                    return { Color: '#ff0000', textAlign: 'right' }
                } else {
                    return { Color: '#000000', textAlign: 'right' }
                }
            },
            footer: farmatearMontos(Round(totalDebe - totalHaber, 2))
        },
        {
            dataField: 'Debe', text: 'Debe', sort: true, csvText: 'Debe', headerAlign: 'right', formatter: (row, cell) => farmatearMontos(cell.Debe), hidden: false, editable: true, align: 'right',
            validator: (newValue, row, column) => {
                return validaDebe(newValue, row);
            },
            footer: (columnData, column, columnIndex) => {
                const total = columnData.reduce((acc, item) => acc + item, 0);
                setTotalDebe(total);
                return farmatearMontos(Round(total, 2));
            }
            , type: 'number',
            footerStyle: { Color: '#ff0000', textAlign: 'right' }
        },
        {
            dataField: 'Haber', text: 'Haber', sort: true, csvText: 'Haber', headerAlign: 'right', hidden: false, editable: true, align: 'right',
            formatter: (row, cell) => farmatearMontos(cell.Haber), type: 'number',
            footer: (columnData, column, columnIndex) => {
                const total = columnData.reduce((acc, item) => acc + item, 0);
                setTotalHaber(total);
                return farmatearMontos(Round(total, 2));
            },
            footerStyle: { Color: '#ff0000', textAlign: 'right' },
            validator: (newValue, row, column) => {
                return validaHaber(newValue, row);
            },
        },];

    const botones = [
        { name: "btnVolver", clase: "btn btn-sm pull-right flipInX animated", evento: () => volverAtras(), leyenda: "", iclase: faReply, tooltip: "Volver" },
        { name: "btnGuardar", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleGuardar(), leyenda: "", iclase: faSave, tooltip: "Guardar" },
        { name: "btnPlantilla", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleModalPl(), leyenda: "", iclase: faList, tooltip: "Plantilla" },
        { name: "btnGuardarNuevo", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleGuardarYNuevo(), leyenda: "", iclase: faFolderPlus, tooltip: "Guardar y Nuevo" },
        { name: "btnBitacora", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleBitacora(), leyenda: "", iclase: faClipboardList, tooltip: "Bitácora" },
    ];

    const botonesModif = [
        { name: "btnVolver", clase: "btn btn-sm pull-right flipInX animated", evento: () => volverAtras(), leyenda: "", iclase: faReply, tooltip: "Volver" },
        { name: "btnGuardar", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleGuardar(), leyenda: "", iclase: faSave, tooltip: "Guardar" },
        { name: "btnPlantilla", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleModalPl(), leyenda: "", iclase: faList, tooltip: "Plantilla" },
        { name: "btnBitacora", clase: "btn btn-sm pull-right flipInX animated", evento: () => handleBitacora(), leyenda: "", iclase: faClipboardList, tooltip: "Bitácora" },
    ];

    const handleGuardar = async () => {

        const optSegopt = optSeg.TOpciones_Menu;
        const _value = (id > 0) ? optSegopt.Editar.value : optSegopt.Nuevo.value;

        const hayErrores = hayErroresLinea(validarBalanceado);
        if (hayErrores.length > 0) {
            Notificacion.error(hayErrores);
        } else {

            let validar = validarMenuOpcion(_value);
            if (!validar) {
                if (id === 0) {
                    await guardarAsiento(true);
                } else {
                    await modificarAsiento();
                }
            }
        }

    }

    const handleGuardarYNuevo = async () => {
        const optSegopt = optSeg.TOpciones_Menu;
        const _value = (id > 0) ? optSegopt.Editar.value : optSegopt.Nuevo.value;
        setGuardarYNuevo(true);

        const hayErrores = hayErroresLinea(validarBalanceado);
        if (hayErrores.length > 0) {
            Notificacion.error(hayErrores);
        } else {
            let validar = validarMenuOpcion(_value);
            if (!validar) {
                if (id === 0) {
                    await guardarAsiento(false);
                }
            }
        }
    }

    const hayErroresLinea = (verifBalanceado = false) => {

        let fila = 0;
        let Error = '';
        let i = 0;
        let Linea = '';
        let Row = 0;
        let _listaDatos = [].concat(listaDatos.filter(x => x.Debe > 0 || x.Haber > 0));

        if (cambioDeFecha()) {
            Error = 'No se puede guardar un asiento en una fecha anterior al mes en curso.';
        }

        if (Datos.Descripcion.value.trim() === '' && Error === '') {
            Error = 'No se puede guardar el asiento ya que necesita una descripción.';
        }

        while (i < _listaDatos.length && Error === '') {

            if ((_listaDatos[i].CuentaStr !== '') || ((_listaDatos[i].Debe + _listaDatos[i].Haber) > 0)) {
                Linea = 'La línea ' + (i + 1).toString();

                if (_listaDatos[i].CuentaStr === '')
                    Error = Linea + ' tiene montos asociados, pero ninguna cuenta válida que referenciar.';
                else if (_listaDatos[i].Centro_CostoStr === '')
                    Error = Linea + ' tiene montos asociados, pero ningún centro de costo válido que referenciar.';

                if (Error !== '')
                    Row = i;
            }

            i++;

        }

        if (verifBalanceado) {
            if (Error === '' && (SumeMontos(true) - SumeMontos(false)) !== 0)
                Error = 'El asiento no se encuentra balanceado.';
        }

        return Error;

    }

    const guardarAsiento = async (guardarYVolver = true) => {

        let Result = false;

        try {

            spinnerModalMostrar(true, 'Guardando asiento');

            if (!cambioDeFecha()) {

                setFModificado(true);
                Result = true;

                const fecha = Datos.FechaAnio.value.toString() + '/' + (parseInt(selectedOptionMes.value) <= 9 ? '0' : '') + selectedOptionMes.value.toString() + '/01';
                const tipo = selectedTipo;
                const _Datos = await siguienteContador()
                const numero = _Datos.Numero.value;
                const Descripcion = Datos.Descripcion.value
                //estado digitado
                const estado = fEstadoAsiento;
                const totalDebitos = SumeMontos(true);
                const totalCreditos = SumeMontos(false);

                const _datos = {
                    Fecha: fecha, Tipo: tipo.value, Numero: numero, Descripcion: Descripcion,
                    Debitos: totalDebitos, Creditos: totalCreditos, DigitadoX: usuario, Estado: estado,
                    empresa: empresa, Usuario_Modifica: usuario, Utilizado: false
                };

                let _lista = listaDatos.filter(x => parseInt(x.Debe) > 0 || parseInt(x.Haber) > 0);

                _lista.forEach((element, i) => {
                    element.Linea = i + 1
                });

                const response = await EncabezadoAsiento_Guardar_Request(token, _datos, _lista);

                if (response.Exitoso) {
                    Notificacion.success('Se guardó el asiento exitosamente.');
                    if (guardarYVolver) {
                        await volverAtras();
                    } else {
                        await limpiarDatos();
                    }
                } else {
                    Notificacion.error(`Error: ${response.Mensaje}`);
                }

            }
        } catch (ex) {
            Notificacion.error(ex.message);
        } finally {
            spinnerModalMostrar(false, '');
        }

        return Result;

    }

    const modificarAsiento = async () => {

        const tipoCreacion = selectedTipoCreacion.value;
        let NomCont = '';
        let Numero = '';

        try {

            spinnerModalMostrar(true, 'Modificando asiento');

            if (!cambioDeFecha()) {

                setFModificado(true);

                const fecha = Datos.FechaAnio.value.toString() + '/' + selectedOptionMes.value.toString().padStart(2, '0') + '/01';
                const fechaAsiento = moment(asiento.Fecha).toDate();
                if (parseInt(selectedOptionMes.value) !== parseInt(fechaAsiento.getMonth() + 1) || parseInt(Datos.FechaAnio.value) !== parseInt(fechaAsiento.getFullYear())) {
                    const _Datos = await siguienteContador()
                    Numero = _Datos.Numero.value;
                }
                else {
                    Numero = asiento.Numero;
                }

                const Descripcion = Datos.Descripcion.value
                //estado digitado
                const estado = validarBalanceado ? Config.eaAprobado : Config.eaDigitado;
                const totalDebitos = SumeMontos(true);
                const totalCreditos = SumeMontos(false);
                const tipo = selectedTipo.value;

                const _datos = {
                    Fecha: fecha, Numero: Numero, Descripcion: Descripcion, TipoCreacion: tipoCreacion,
                    Debitos: totalDebitos, Creditos: totalCreditos, DigitadoX: usuario, Estado: estado,
                    Usuario_Modifica: usuario, Utilizado: false, id: asiento.id, Tipo: tipo, empresa: empresa,
                    AprobadoX: Config.Modulo
                };

                let _lista = listaDatos.filter(x => parseInt(x.Debe) > 0 || parseInt(x.Haber) > 0);

                _lista.forEach((element, i) => {
                    element.Linea = i + 1
                });

                const response = await EncabezadoAsiento_Modificar_Request(token, _datos, _lista);

                if (response.Exitoso) {
                    Notificacion.success('Se modificó el asiento exitosamente.');
                    await volverAtras();
                } else {
                    Notificacion.error(`Error: ${response.Mensaje}`);
                }

            }
        } catch (ex) {
            Notificacion.error(ex.message);
        } finally {
            spinnerModalMostrar(false, '');
        }
    }

    const limpiarDatos = async () => {

        await cargarDatos(true);

    }

    const cambioDeFecha = () => {

        let result = false;
        let fecha = moment(Datos.FechaAnio.value.toString() + '/' + (parseInt(selectedOptionMes.value) <= 9 ? '0' : '') + selectedOptionMes.value.toString() + '/01').toDate();
        let periodo = moment(datosEmpresa.Periodo).toDate();
        let _Datos = { ...Datos };

        if (fecha < periodo) {
            setSelectedOptionMes(itemSelect(moment(periodo).format('MM'), listaMeses));
            _Datos.FechaAnio.value = periodo.getFullYear();
            setDatos(_Datos);

            result = true;
        }

        return result;

    }

    const validaDebe = (newValue, row) => {
        setTotalDebe(SumeMontos(true));
        setTotalHaber(SumeMontos(false));
        if (!isNaN(newValue)) {
            if (parseFloat(newValue) > 0 && parseFloat(row.Haber) == 0) {
                return true;
            } else if (parseFloat(newValue) > 0 && parseFloat(row.Haber) > 0) {
                return {
                    valid: false,
                    message: '¡No puede llenar Debe y Haber en la misma fila!'
                }
            } else {
                if (parseFloat(newValue) >= 0) {
                    return true;
                } else {
                    return {
                        valid: false,
                        message: '¡Debe ingresar un valor numérico!'
                    }
                }
            }
        } else {
            return {
                valid: false,
                message: '¡Debe ingresar un valor numérico!'
            }
        }
    }

    const validaHaber = (newValue, row) => {
        setTotalDebe(SumeMontos(true));
        setTotalHaber(SumeMontos(false));
        if (!isNaN(newValue)) {
            if (parseFloat(newValue) > 0 && parseFloat(row.Debe) == 0) {
                return true;
            } else if (parseFloat(newValue) > 0 && parseFloat(row.Debe) > 0) {
                return {
                    valid: false,
                    message: '¡No puede llenar Debe y Haber en la misma fila!'
                }
            } else {
                if (parseFloat(newValue) >= 0) {
                    return true;
                } else {
                    return {
                        valid: false,
                        message: '¡Debe ingresar un valor numérico!'
                    }
                }
            }
        } else {
            return {
                valid: false,
                message: '¡Debe ingresar un valor numérico!'
            }
        }
    }

    const handleModal = async (cell, row) => {

        const modal = true;
        const _indexCost = row;


        if (!!cell.Cuenta) {
            if (cell.Cuenta != -1) {
                spinnerModalMostrar(true, 'Cargando datos');
                const response = await CentroCosto_Lista_CXCC_Request(token, empresa, cell.Cuenta);
                spinnerModalMostrar(false, '');

                let _listCentroCostoFiltro = [];

                if (response.Exitoso) {
                    _listCentroCostoFiltro = response.Datos;
                } else {
                    Notificacion.error(response.Mensaje);
                    await volverAtras();
                    return;
                }

                const _idCCObj = cell.llave.toString() + 'B';
                setSelectModal(modal), setListCentroCosto(_listCentroCostoFiltro), setListCentroCostoFiltro(_listCentroCostoFiltro);
                setIndexCost(_indexCost), setIdCCObj(_idCCObj);

            } else {
                Notificacion.warning('Debe seleccionar una cuenta contable.');
            }
        } else {
            Notificacion.warning('Debe seleccionar una cuenta contable.');
        }

    }

    const handleCuentaModal = (cell, columnIndex, row, rowIndex) => {

        const indexC = listaDatos.findIndex((element) => element.llave === cell.llave);

        setIndexC(indexC);
        setSelectModalTree(true);
        setPColumn(cell);
        setPColumnIndex(columnIndex);
        setPRow(row);
        setPRowIndex(rowIndex);
        setIdCtaObj(cell.llave);

    }

    const onValidarCCosto = (newValue, row, column) => {
        if (row.Centro_CostoStr !== newValue) {
            if (column.dataField == 'Centro_CostoStr') {
                if (!!row.Cuenta) {
                    if (row.Cuenta != -1) {
                        const validacion = validaCCosto(listCCosto, row.Cuenta, newValue, listCXCC)
                        if (validacion.length > 0) {
                            return {
                                valid: false,
                                message: validacion
                            };
                        } else {
                            const listaCCosto = listCCosto.filter(item => item.Cuenta == newValue);
                            row.Centro_CostoNom = listaCCosto[0].Nombre;
                            row.Centro_Costo = listaCCosto[0].ID;
                            return true;
                        }
                    } else {
                        return {
                            valid: false,
                            message: 'Debe seleccionar una cuenta contable'
                        };
                    }
                } else {
                    return {
                        valid: false,
                        message: 'Debe seleccionar una cuenta contable'
                    };
                }
            }
        } else {
            return true;
        }
    }

    const onValidarCuenta = (newValue, row, column) => {
        if (row.CuentaStr !== newValue) {

            if (column.dataField == 'CuentaStr') {
                const validacion = validaCuenta(listCuentas, newValue)

                if (validacion.length > 0) {
                    return {
                        valid: false,
                        message: validacion
                    };
                } else {

                    const _listaCuenta = listCuentas.filter(item => item.Cuenta == newValue || item.CuentaStr == newValue);

                    row.NombreCuenta = _listaCuenta[0].Nombre;
                    row.CuentaStr = _listaCuenta[0].Cuenta;
                    row.Cuenta = _listaCuenta[0].ID;

                    return true;
                }
            }
        } else {
            return true;
        }
    }

    const onValidarFecha = (newValue, row, column) => {
        if (newValue !== '') {
            if (!moment(newValue).isValid()) {
                return {
                    valid: false,
                    message: 'Debe ingresar una fecha válida'
                };
            } else {
                return true;
            }
        } else {
            row.Fecha = null;
            return true;
        }
    }

    const volverAtras = async () => {
        historyMenu.push(SiteRutas.Asientos);

        let _id = parseInt(props.match.params.id);

        if (_id > 0) {
            await CambiarUtilizado(_id, false);
        }

    }

    const spinnerModalMostrar = (mostrar, texto, tipo = 3) => {
        setSpinnerModal({ mostrar: mostrar, texto: texto, tipo: tipo });
    }

    const ordenarArreglo = (a, b, columna) => {
        if (a[columna] < b[columna]) {
            return -1;
        }
        if (a[columna] > b[columna]) {
            return 1;
        }
        return 0;
    }

    const cargarSeguridad = async () => {
        const _MenuNomb = await cargarMenuNombre(Config.Modulo, optSeg.TMenuSistema.Asientos.value);
        let _menuId = 0;

        if (_MenuNomb.ID != undefined) {
            _menuId = _MenuNomb.ID;
        }

        let _menuOpciones = null;
        if (_menuId > 0) {
            _menuOpciones = await cargarMenuOpciones(Config.Modulo, usuarioS, _menuId);
        }
        setMenuId(_menuId), setMenuOpciones(_menuOpciones);
    }

    //Seguridad
    const cargarMenuOpciones = async (pModuloId, pUsuarioId, pMenuId) => {
        try {

            let listMO = await Obtener_MenuOpciones_Lista_Request(token, pModuloId, pUsuarioId, pMenuId);
            if (listMO.Exitoso === false) {
                return null;
            }
            return listMO.Datos;
        }
        catch (err) {
            Notificacion.error(`Error: cargarMenuOpciones.`);
        }
    }

    const cargarMenuNombre = async (pModulo, pMenuNombre) => {
        try {
            let listMON = await Obtener_MenuNombre_Request(token, pModulo, pMenuNombre);
            if (listMON.Exitoso == false) {
                return null;
            }
            return listMON.Datos;
        }
        catch (err) {
            Notificacion.error(`Error: cargarMenuNombre.`);
        }
    }

    const validarMenuOpcion = (pOpcion) => {
        let validar = false;
        let _menuOpciones = menuOpciones;
        const optSegopt = optSeg.TOpciones_Menu;
        let resultado = _menuOpciones.filter((item) => item.Opcion_Nombre == pOpcion);
        if (resultado.length > 0) {
            if (resultado[0].Opcion_Validar) {
                setShowModalSeguridad(true); setOpcionValidar(resultado[0].Opcion_Id); setOpcionValidarNombre(pOpcion);
                validar = true;
            }
        } else {
            setShowModalSeguridad(true); setOpcionValidar(resultado[0].Opcion_Id); setOpcionValidarNombre(pOpcion);
            validar = true;
        }
        return validar;
    };

    const handleCerrarModal = () => setShowModalSeguridad(false);

    const cerrarModal = () => {

        setSelectModal(false);
        setSelectedCentroCosto(undefined);
        setIndexCost(indexCost);
        setRowSelected(undefined);

    }

    const onActionResultModal = (pValido) => {
        if (pValido) {
            let _OpcionNom = opcionValidarNombre;
            setShowModalSeguridad(false); setOpcionValidar(0); setOpcionValidarNombre('');
            const _optSegopt = optSeg.TOpciones_Menu;

            switch (_OpcionNom) {
                case _optSegopt.Nuevo.value:
                    guardarAsiento(!guardarYNuevo);
                    break;
                case _optSegopt.Editar.value:
                    modificarAsiento();
                    break;
                case _optSegopt.Plantilla.value:
                    cargarDatosPlantilla();
                    break;
                default:
                    break;
            }
        }
    }

    const cargarTiposAsiento = async (_Datos, Periodo, cargarContador) => {

        const response = await TipoAsiento_Listar_Request(token, empresa);
        let lista = [];
        if (response.Exitoso) {
            if (Array.isArray(response.Datos) && response.Datos.length > 0) {
                lista = [...response.Datos].map(x => ({ value: x.ID, label: x.Nombre, mensual: x.Mensual }));
                setListaTipo(lista);

                setSelectedTipo(lista[0]);

                if (cargarContador) {
                    await obtenerContador(parseInt(_Datos.FechaAnio.value), Periodo.getMonth() + 1, lista[0], _Datos);
                }

            } else {
                Notificacion.error("No se encontraron datos para: Tipo de Asiento.");
                await volverAtras();
            }
        }
        else {
            Notificacion.error(response.Mensaje);
            await volverAtras();
        }
        return lista;
    }

    const llenadoListaArbol = (pLista) => {
        let _Datos = [];
        const _Lista = pLista;
        _Datos.push({ "title": empresaNombre, "subtitle": "", "padre": -1, "value": 0 });

        _Lista.map(function (item, index) {
            _Datos.push({ "title": item.Cuenta + " " + item.Nombre, "subtitle": "", "padre": (item.Padres.length > 0 ? parseInt(item.Padres.substring(item.Padres.length - 6, item.Padres.length)) : 0), "value": item.ID });
        });

        return _Datos;
    }

    const carga_ListTree = async () => {

        const response = await Catalogo_Lista_Request(token, empresa, 0);
        let _lista = [];
        if (response.Exitoso) {
            const _listCuentas = response.Datos;
            const _listCuentasCont = llenadoListaArbol(_listCuentas);
            setListCuentas(_listCuentas);
            _lista = datosArbol(_listCuentasCont);
        }
        else {
            Notificacion.error(response.Mensaje);
            await volverAtras();
        }

        return _lista;

    }

    const cargarCentrosDeCosto = async () => {

        let response = await CentroCosto_Lista_CCC_Request(token, empresa);

        if (response.Exitoso) {
            if (Array.isArray(response.Datos)) {
                setListCCosto(response.Datos);
            } else {
                Notificacion.error('No hay datos para: Centros de Costo.');
                await volverAtras();
            }
        }
        else {
            Notificacion.error(response.Mensaje);
            await volverAtras();
        }

        response = await CentroCosto_Lista_CXCCEmpresa_Request(token, empresa);

        if (response.Exitoso) {
            if (Array.isArray(response.Datos)) {
                setListCXCC(response.Datos);
            } else {
                Notificacion.error('No hay datos para: Centros de Costo.');
                await volverAtras();
            }
        }
        else {
            Notificacion.error(response.Mensaje);
            await volverAtras();
        }

    }

    const CambiarUtilizado = async (Id, Utilizado) => {
        const _asiento = { id: Id, Utilizado: Utilizado }

        const response = await EncabezadoAsiento_ModificarUtilizado_Request(token, _asiento);

        if (response.Exitoso) {
            return true;
        } else {
            Notificacion.error(`Error: ${response.Mensaje}`);
            return false;
        }

    }

    const cargarDetalleAsiento = async (Asiento, Fecha) => {

        const response = await DetalleAsiento_Listar_Request(token, Asiento);

        const item = {
            Asiento: 0,
            Centro_Costo: 0,
            Centro_CostoStr: "",
            Credito: false,
            Cuenta: 0,
            CuentaStr: "",
            Debe: 0,
            Documento: "",
            Fecha: Fecha,
            Fecha_Actualizacion: new Date("1900-01-01"),
            Haber: 0,
            Linea: 0,
            Monto: 0,
            MsgError: "",
            NombreCuenta: "",
            Referencia: "",
            Referencia2: "",
            TipoDoc: 0,
            llave: ""
        };

        if (response.Exitoso) {
            if (Array.isArray(response.Datos)) {
                let _lista = [...response.Datos];
                let _debe = 0;
                let _haber = 0;
                _lista.forEach((element, i) => {
                    element.llave = element.Linea.toString();
                    _debe = _debe + parseFloat(element.Debe);
                    _haber = _haber + parseFloat(element.Haber);
                });

                setTotalDebe(_debe);
                setTotalHaber(_haber);

                _lista.push(item);

                setListaDatos(_lista);

            } else {
                Notificacion.error(`${response.Mensaje}`);
                let _lista = [];
                _lista.push(item);
            }
        }
        else {
            Notificacion.error(response.Mensaje);
            if(response.Mensaje != 'No hay datos por mostrar.'){
                await volverAtras();
                return false
            }else{
                let _lista = [];
                _lista.push(item);
                setListaDatos(_lista);
                return true;
            }
        }
    }

    const cargarAsiento = async (Asiento, _Datos) => {

        let Fecha = new Date();
        let response = await EncabezadoAsiento_ObtenerAsiento_Request(token, Asiento);

        if (response.Exitoso) {
            let _asiento = { ...response.Datos };

            if (_asiento.Creacionlocal) {

                const _estado = _asiento.Estado;
                const _resultado = (_asiento.id > 0);

                if (_resultado) {

                    if ((_estado === Config.eaDigitado || _estado === Config.eaAprobado)) {

                        if (!_asiento.Utilizado) {

                            await CambiarUtilizado(_asiento.id, true);

                            setFModificado(false);

                            setAsiento(response.Datos);
                            Fecha = new Date(response.Datos.Fecha);

                            const _listaTipo = await cargarTiposAsiento(_Datos, Fecha, false);

                            setSelectedTipo(_listaTipo.filter(x => x.value === response.Datos.Tipo)[0]);
                            _Datos.Tipo.attributes.readOnly = true;
                            _Datos.FechaMes.attributes.readOnly = true;
                            _Datos.FechaAnio.attributes.readOnly = true;
                            _Datos.Numero.value = response.Datos.Numero.toString().padStart(5, '0');
                            setValidarBalanceado(parseInt(response.Datos.Estado) === parseInt(Config.eaAprobado));
                            _Datos.FechaAnio.value = Fecha.getFullYear();
                            setSelectedOptionMes(itemSelect(Fecha.getMonth() + 1, listaMeses));
                            _Datos.Descripcion.value = response.Datos.Descripcion;

                            await cargarDetalleAsiento(Asiento, Fecha);

                            setDatos(_Datos);

                        } else {
                            Notificacion.warning('Este Asiento está siento utilizado por otro Usuario.');
                            await volverAtras();
                        }
                    } else {
                        Notificacion.warning('Este Asiento ya no está disponible para modificar, porque otro usuario cambio su estado.');
                        await volverAtras();
                    }
                } else {
                    Notificacion.warning('No se encontró el Asiento.');
                    await volverAtras();
                }
            } else {
                Notificacion.warning('Este asiento fue creado en un auxiliar y no puede modificarse.');
                await volverAtras();
            }
        } else {
            Notificacion.error(response.Mensaje);
            await volverAtras();
        }

    }

    const ingresarDetalle = (Periodo, limpiar = false) => {

        let _listaDatos = limpiar ? [] : [].concat(listaDatos);

        let item = {
            Asiento: 0,
            Centro_Costo: 0,
            Centro_CostoStr: "",
            Credito: false,
            Cuenta: 0,
            CuentaStr: "",
            Debe: 0,
            Documento: _listaDatos.length === 0 ? "" : _listaDatos[_listaDatos.length - 1].Documento,
            Fecha: Periodo,
            Fecha_Actualizacion: new Date("1900-01-01"),
            Haber: 0,
            Linea: (_listaDatos.length + 1),
            Monto: 0,
            MsgError: "",
            NombreCuenta: "",
            Referencia: _listaDatos.length === 0 ? Datos.Descripcion.value : _listaDatos[_listaDatos.length - 1].Referencia,
            Referencia2: "",
            TipoDoc: 0,
            llave: (_listaDatos.length + 1).toString()
        };

        _listaDatos.push(item);

        setListaDatos(_listaDatos);

    }

    const cargarEncaPlantilla = async (Plantilla, _Datos, Fecha) => {

        let response = await EncaPlantillas_Consultar_Request(token, Plantilla);
        const _listaTipo = await cargarTiposAsiento(_Datos, Fecha, false);
        let encaPlantilla = null;
        let _selectedTipo = null;

        setFModificado(false);

        if (response.Exitoso) {
            setPlantilla(response.Datos);
            encaPlantilla = { ...response.Datos };
            _selectedTipo = _listaTipo.filter(x => x.value === response.Datos.Tipo_Asiento)[0];
            setSelectedTipo(_selectedTipo);

            await obtenerContador(moment(Fecha).year(), moment(Fecha).month() + 1, _selectedTipo, undefined);

            encaPlantilla.FechaAct = moment(Fecha).format("YYYY/MM/DD");

            response = await EncaPlantillas_ModificarFechaAct_Request(token, encaPlantilla);

            if (!response.Exitoso) {
                Notificacion.error(`Error: ${response.Mensaje}`);
                await volverAtras();
            }

            _Datos.FechaAnio.value = Fecha.getFullYear();
            setSelectedOptionMes(itemSelect(Fecha.getMonth() + 1, listaMeses));
            _Datos.Descripcion.value = encaPlantilla.Descripcion;

            if (encaPlantilla.Aprobado) {
                setFEstadoAsiento(Config.eaAprobado);
            } else {
                setFEstadoAsiento(Config.eaDigitado);
            }

            if (parseInt(encaPlantilla.Tipo) === Config.tpPorcentual) {
                setSelectModalMontoPorc(true);
            } else {
                await cargarDetallePlantilla(encaPlantilla.ID, encaPlantilla.Tipo, 0, Fecha);
            }

            setDatos(_Datos);

        } else {
            Notificacion.error(response.Mensaje);
            volverAtras();
        }

    }

    const cargarDetallePlantilla = async (Plantilla, Tipo, Monto, Periodo) => {

        const response = await DetallePlantillas_Listar_Request(token, Plantilla);

        if (response.Exitoso) {
            if (Array.isArray(response.Datos)) {
                const _Lineas = [...response.Datos];
                let _lista = [];
                let _debe = 0;
                let _haber = 0;

                const item = {
                    Asiento: 0,
                    Centro_Costo: 0,
                    Centro_CostoStr: "",
                    Credito: false,
                    Cuenta: 0,
                    CuentaStr: "",
                    Debe: 0,
                    Documento: "",
                    Fecha: Periodo,
                    Fecha_Actualizacion: new Date("1900-01-01"),
                    Haber: 0,
                    Linea: 0,
                    Monto: 0,
                    MsgError: "",
                    NombreCuenta: "",
                    Referencia: "",
                    Referencia2: "",
                    TipoDoc: 0,
                    llave: ""
                };

                let itemTmp = null;

                for (let i = 0; i < _Lineas.length; i++) {
                    itemTmp = { ...item };

                    itemTmp.llave = _Lineas[i].Linea.toString();
                    itemTmp.Fecha = Periodo;
                    itemTmp.Cuenta = _Lineas[i].Cuenta;
                    itemTmp.CuentaStr = _Lineas[i].CuentaStr;
                    itemTmp.NombreCuenta = _Lineas[i].NombreCuenta;
                    itemTmp.Referencia = _Lineas[i].Descripcion;
                    itemTmp.Documento = _Lineas[i].Documento;
                    itemTmp.Centro_Costo = _Lineas[i].Centro_Costo;
                    itemTmp.Centro_CostoStr = _Lineas[i].Centro_CostoStr;

                    if (Tipo === Config.tpSimple) {
                        itemTmp.Debe = _Lineas[i].Debito;
                        itemTmp.Haber = _Lineas[i].Credito;
                    } else if (Tipo === Config.tpPorcentual) {
                        itemTmp.Debe = Monto * _Lineas[i].Debito / 100;
                        itemTmp.Haber = Monto * _Lineas[i].Credito / 100;
                    }

                    _lista.push(itemTmp);

                    _debe = _debe + parseFloat(itemTmp.Debe);
                    _haber = _haber + parseFloat(itemTmp.Haber);
                };

                setTotalDebe(_debe);
                setTotalHaber(_haber);

                _lista.push(item);

                setListaDatos(_lista);

            } else {
                Notificacion.error('No hay datos para: Plantilla Detalle.');
                volverAtras();
            }
        }
        else {
            Notificacion.error(response.Mensaje);
            volverAtras();
        }

    }

    const cargarDatos = async (limpiar = false) => {
        let _Datos = { ...Datos }
        let Periodo = null;

        try {
            spinnerModalMostrar(true, 'Cargando Datos');
            const _id = parseInt(props.match.params.id);
            const _idPlantilla = parseInt(props.match.params.idPlantilla);

            setId(_id);
            setIdPlantilla(_idPlantilla);

            let response = await Empresa_Consulta_Request(token, empresa);

            if (response.Exitoso) {
                setDatosEmpresa(response.Datos);
                Periodo = new Date(response.Datos.Periodo);
            } else {
                Notificacion.error(response.Mensaje);
                await volverAtras();
            }

            await cargarSeguridad();

            const _listCuentasContTemp = await carga_ListTree();

            setListCuentasCont(_listCuentasContTemp);

            await cargarCentrosDeCosto();

            if (_id > 0) {
                setFModificado(false);
                await cargarAsiento(_id, _Datos);
            } else if (_id === 0 && _idPlantilla > 0) {

                await cargarEncaPlantilla(_idPlantilla, _Datos, Periodo);

            }
            else {

                setValidarBalanceado(false);
                setFModificado(false);
                setSelectedTipoCreacion(tipoCreacion[0]);

                if (limpiar) {
                    _Datos.Descripcion.value = "";
                    setTotalDebe(0);
                    setTotalHaber(0);
                }

                if (parseInt(_Datos.FechaAnio.value) === 0) {
                    _Datos.FechaAnio.value = Periodo.getFullYear();
                    setSelectedOptionMes(itemSelect(Periodo.getMonth() + 1, listaMeses));
                    setDatos(_Datos);
                }

                const _listaTipo = await cargarTiposAsiento(_Datos, Periodo, true);
                ingresarDetalle(Periodo, limpiar);
                if (parseInt(_Datos.FechaAnio.value) === 0) {
                    _Datos.FechaAnio.value = Periodo.getFullYear();
                    setSelectedOptionMes(itemSelect(Periodo.getMonth() + 1, listaMeses));
                    setDatos(_Datos);
                }
            }

        } catch (ex) {
            Notificacion.error(ex.message);
        } finally {
            spinnerModalMostrar(false, '', 3);
        }

    }

    useEffect(() => {
        const carga = async () => {
            await cargarDatos()
        }
        carga()
    }, [])

    const obtenerFinPeriodo = (IniPeriodo) => {
        let Result = new Date();

        if ((IniPeriodo.getMonth() + 1) === 1) {
            Result = new Date(IniPeriodo.getFullYear(), 11, 31);
        }
        else {
            Result = moment(new Date(IniPeriodo.getFullYear() + 1, IniPeriodo.getMonth(), 1)).add(-1, 'days').toDate();
        }

        return Result;
    }

    const buscarFronteras = async (params) => {

        let Periodo = new Date();
        let IniPeriodo = new Date();
        let FinPeriodo = new Date();

        if (datosEmpresa == undefined) {
            let response = await Empresa_Consulta_Request(token, empresa);

            if (response.Exitoso) {
                setDatosEmpresa(response.Datos);
                Periodo = new Date(response.Datos.Periodo);
                IniPeriodo = new Date(response.Datos.InicioPeriodo);
            } else {
                Notificacion.error(response.Mensaje);
                await volverAtras();
            }
        } else {
            Periodo = new Date(datosEmpresa.Periodo);
            IniPeriodo = new Date(datosEmpresa.InicioPeriodo);
        }

        FinPeriodo = obtenerFinPeriodo(IniPeriodo);

        if (params.Fecha.getMonth() <= FinPeriodo.getMonth()) {
            if ((IniPeriodo.getMonth() + 1) === 1) {
                params.Inicio = new Date(params.Fecha.getFullYear(), IniPeriodo.getMonth(), 1);
                params.Fin = moment(new Date(params.Fecha.getFullYear() + 1, IniPeriodo.getMonth(), 1)).add(-1, 'days').toDate();
            } else {
                params.Inicio = new Date(params.Fecha.getFullYear() - 1, IniPeriodo.getMonth(), 1);
                params.Fin = moment(new Date(params.Fecha.getFullYear(), IniPeriodo.getMonth(), 1)).add(-1, 'days').toDate();
            }
        } else {
            params.Inicio = new Date(params.Fecha.getFullYear(), IniPeriodo.getMonth(), 1);
            params.Fin = moment(new Date(params.Fecha.getFullYear() + 1, IniPeriodo.getMonth(), 1)).add(-1, 'days').toDate();
        }

        return params;

    }

    const obtenerContador = async (Anio, Mes, selTipo = undefined, _Datos = undefined) => {

        let Nombre = '';
        let Periodo = new Date();

        if (_Datos === undefined) {
            _Datos = { ...Datos };
        }

        if (Anio === 0) {
            Periodo = moment(_Datos.FechaAnio.value.toString() + '/' + selectedOptionMes.value.toString().padStart(2, '0') + '/01').toDate();
        } else {
            Periodo = Periodo = moment(Anio.toString() + '/' + Mes.toString().padStart(2, '0') + '/01').toDate();
        }

        if (selTipo == undefined) {
            selTipo = selectedTipo;
        }

        if (selTipo.mensual) {
            Nombre = selTipo.label.trim() + '_' + moment(Periodo).format('MM');
        } else {
            Nombre = selTipo.label.trim() + '_01';
        }

        let Fechas = { Fecha: Periodo, Inicio: new Date(), Fin: new Date() };
        await buscarFronteras(Fechas);

        let response = await EncabezadoAsiento_ObtenerContador_Request(token, empresa, moment(Fechas.Inicio).format('YYYY/MM/DD'), Nombre);

        if (response.Exitoso) {
            const Numero = response.Datos.id;
            _Datos.Numero.value = Numero.toString().padStart(5, '0');
        }
        else {
            const Numero = 1;
            _Datos.Numero.value = Numero.toString().padStart(5, '0');
        }

        setDatos(_Datos);

        return _Datos;

    }

    const siguienteContador = async () => {

        let Nombre = '';
        let Periodo = new Date();

        let _Datos = { ...Datos };

        Periodo = moment(_Datos.FechaAnio.value.toString() + '/' + (parseInt(selectedOptionMes.value) <= 9 ? '0' : '') + selectedOptionMes.value.toString() + '/01').toDate();

        if (selectedTipo.mensual) {
            Nombre = selectedTipo.label.trim() + '_' + moment(Periodo).format('MM');
        } else {
            Nombre = selectedTipo.label.trim() + '_01';
        }

        let Fechas = { Fecha: Periodo, Inicio: new Date(), Fin: new Date() };
        await buscarFronteras(Fechas);

        let response = await Contabilidad_ObtenerContadorAsiento_Request(token, empresa, moment(Fechas.Inicio).format('YYYY/MM/DD'), Nombre);

        if (response.Exitoso) {
            const Numero = response.Datos.Numero;
            _Datos.Numero.value = Numero.toString().padStart(5, '0');
        }
        else {
            const Numero = 1;
            _Datos.Numero.value = Numero.toString().padStart(5, '0');
        }

        setDatos(_Datos);

        return _Datos;

    }

    const handleSelectedTipo = async (selTipo) => {
        setSelectedTipo(selTipo);

        await obtenerContador(0, undefined, selTipo, undefined);

    }

    const onhandleSelectedOptionMes = async (SelOptionMes) => {
        setSelectedOptionMes(SelOptionMes);

        await obtenerContador(Datos.FechaAnio.value, SelOptionMes.value, selectedTipo, undefined);

    }

    const onhandleAnioChange = async (event) => {
        let _Datos = { ...Datos }

        const valido = validarIntVig(event.target.value);

        if (valido) {
            _Datos.FechaAnio.value = event.target.value;
            await obtenerContador(_Datos.FechaAnio.value, selectedOptionMes.value, selectedTipo, _Datos);
        }

    }

    const validarAnio = (ev) => {
        const text = /^[0-9]+$/;
        const year = ev.target.value;

        let _Datos = { ...Datos };

        if (
            ev.type == "blur" ||
            (year.length == 4 && ev.keyCode != 8 && ev.keyCode != 46)
        ) {
            if (year != 0) {
                const current_year = new Date().getFullYear();

                if (year != "" && !text.test(year)) {

                    _Datos.FechaAnio.value = current_year;

                    setDatos(_Datos);

                    Notificacion.warning("Debe ingresar un valor numérico.");

                    return false;
                }

                if (year.length != 4) {

                    _Datos.FechaAnio.value = current_year;
                    setDatos(_Datos);
                    Notificacion.warning("Debe ingresar un año válido.");

                    return false;
                }

                if (year < 1900 || year > current_year) {

                    _Datos.FechaAnio.value = current_year;

                    setDatos(_Datos);

                    Notificacion.warning("Debe ingresar un año válido.");

                    return false;
                }
                return true;
            }
        }
    }

    const validarSoloNumeros = (ev) => {
        const text = /^[0-9]+$/;

        const value = ev.target.value;

        if (ev.type == "blur" && ev.keyCode != 8 && ev.keyCode != 46) {
            if (value != "" && !text.test(value)) {
                Notificacion.warning("Debe ingresar un valor numérico.");
                return false;
            } else if (value == "") {
                return false;
            }
        }

        return true;
    }

    const onChangeInput = (e) => {

        const name = e.target.name;
        const value = e.target.value;

        let newAttributes = Datos[name].attributes;
        let _Datos = Object.assign({}, Datos, {
            [name]: { value: value, attributes: newAttributes },
        });

        if (name === 'Descripcion') {
            let _listaDatos = [].concat(listaDatos);
            if (_listaDatos.length === 1) {
                _listaDatos[0].Referencia = value;
                setListaDatos(_listaDatos);
            }
        }

        setDatos(_Datos);

    }

    const onChangeInputPorMonto = (e) => {
        const name = e.target.name;
        const value = e.target.value;

        const valido = validarDecimal(value);

        if (valido) {

            let newAttributes = Datos[name].attributes;

            const _Datos = Object.assign({}, Datos, {
                [name]: {
                    value: value,
                    attributes: newAttributes,
                    id: name,
                    name: name,
                },
            });

            setDatos(_Datos);
        }
    }

    const onChangeEditar = (e) => {
        const name = e.target.name;

        const value = parseFloat(Datos[name].value.toString() === "" ? "0" : Datos[name].value.toString());
        let newAttributes = Datos[name].attributes;
        const _Editando = !newAttributes.Editando;
        newAttributes.Editando = _Editando;
        const _Datos = Object.assign({}, Datos, {
            [name]: { value: value, attributes: newAttributes },
        });
        if (_Editando) {
            e.target.type = "text";
            e.target.value = value;
            e.target.setSelectionRange(0, e.target.value.toString().length);
            e.target.type = "number";
        }

        setDatos(_Datos);
    }

    const onFormato = (valor) => {
        return farmatearMontos(valor);
    };

    const onRowSelect = (row) => {
        setFilaSeleccionada(row);
    };

    const onRowSelectBusquedaTree = (row) => {
        setSelectedCuenta(row);
    }

    const onRowSelectBusqueda = (row) => {
        setSelectedCentroCosto(row);
    }

    const cerrarModalTree = () => {
        setIndexC(-1);
        setSelectModalTree(false);
    }

    const handleCerrarModalMontoPorc = async () => {
        setSelectModalMontoPorc(false);
        historyMenu.push(SiteRutas.Plantillas);
    }

    const handleAceptarMontoPorc = async () => {

        if (Datos.Monto.value > 0) {
            setSelectModalMontoPorc(false);

            await cargarDetallePlantilla(idPlantilla, plantilla.Tipo, Datos.Monto.value, datosEmpresa.Periodo);

        } else {
            Notificacion.error('Debe ingresar un monto válido.');
        }

    }

    const seleccionModalTree = async () => {

        if (!!selectedCuenta) {
            if (!selectedCuenta.node.children) {

                const listCCont = listCuentas.filter(item => item.ID == selectedCuenta.node.value);
                let _pColumn = { ...pColumn };

                _pColumn.Cuenta = listCCont[0].ID;
                _pColumn.CuentaStr = listCCont[0].Cuenta;
                _pColumn.NombreCuenta = listCCont[0].Nombre;

                spinnerModalMostrar(true, 'Cargando datos', 3);
                const response = await CentroCostos_CentroDefault_Request(token, empresa, _pColumn.Cuenta);
                spinnerModalMostrar(false, '', 3);

                let _listaDatos = [].concat(listaDatos);

                _listaDatos[indexC].Cuenta = _pColumn.Cuenta;
                _listaDatos[indexC].CuentaStr = _pColumn.CuentaStr;
                _listaDatos[indexC].NombreCuenta = _pColumn.NombreCuenta;

                if (response.Exitoso) {
                    _listaDatos[indexC].Centro_Costo = response.Datos.ID;
                    _listaDatos[indexC].Centro_CostoStr = response.Datos.CentroCosto;
                    _listaDatos[indexC].Centro_CostoNom = response.Datos.Nombre;
                }
                else {
                    Notificacion.error(response.Mensaje);
                }

                setListaDatos(_listaDatos);
                setActTabla(true);
                setSelectedCuenta(undefined);
                setSelectModalTree(false);
                setIndexC(-1);
                setPColumn(_pColumn);

            }
            else {
                Notificacion.error('La cuenta selccionada es padre.');
                setSelectModalTree(false);
                setSelectedCuenta(undefined);
            }
        }
        else {
            Notificacion.warning('Debe seleccionar un registro.');
        }
    }

    const selectRow = { onSelect: onRowSelect, hideSelectColumn: true, mode: "radio", clickToSelect: true, clickToEdit: true, bgColor: '#d73220', style: { color: '#ffffff' } };

    const cellEdit = {
        mode: "click",
        blurToSave: true,
        autoSelectText: true,
        afterSaveCell: (oldValue, newValue, row, column) => {
            setTotalDebe(SumeMontos(true));
            setTotalHaber(SumeMontos(false));

            if (column.dataField === "Debe" || column.dataField === "Haber") {
                if (parseInt(listaDatos[listaDatos.length - 1].Debe) > 0 || parseInt(listaDatos[listaDatos.length - 1].Haber) > 0) {
                    ingresarDetalle(new Date(parseInt(Datos.FechaAnio.value), parseInt(selectedOptionMes.value) - 1, 1));
                }
            }
        },
    };

    const seleccionModal = () => {

        if (!!selectedCentroCosto) {

            const listCCost = listCCosto.filter(item => item.ID == selectedCentroCosto.ID);

            let _listaDatos = [].concat(listaDatos);
            _listaDatos[indexCost].Centro_Costo = listCCost[0].ID;
            _listaDatos[indexCost].Centro_CostoStr = listCCost[0].CentroCosto;
            _listaDatos[indexCost].Centro_CostoNom = listCCost[0].Nombre;

            setListaDatos(_listaDatos);
            setSelectedCentroCosto(undefined);
            setSelectModal(false);
            setIndexCost(indexCost);

        }
        else {
            Notificacion.warning('Debe seleccionar un registro.');
        }
    }

    const handleChangeSearch = (event) => {

        let _listCentroCostoFiltro = listCentroCosto;
        _listCentroCostoFiltro = _listCentroCostoFiltro.filter(function (item) {
            return item.CentroCosto.toLowerCase().search(
                event.target.value.toLowerCase()) !== -1;
        });

        if (_listCentroCostoFiltro.length == 0) {
            _listCentroCostoFiltro = listCentroCosto;

            _listCentroCostoFiltro = _listCentroCostoFiltro.filter(function (item) {
                return item.Nombre.toLowerCase().search(
                    event.target.value.toLowerCase()) !== -1;
            });
        }

        setListCentroCostoFiltro(_listCentroCostoFiltro);

    }

    const rowStyleLista = (row, rowIndex) => {
        const style = {};
        if (row.DebeGuardar == -1) {
            style.color = '#21aba0';
        } else {
            style.color = 'black';
        }

        return style;
    }

    const SumeMontos = (Debe) => {

        let Result = parseFloat(0);

        for (let i = 0; i < listaDatos.length - 1; i++) {
            if (Debe)
                Result = Result + parseFloat(listaDatos[i].Debe);
            else
                Result = Result + parseFloat(listaDatos[i].Haber);
        }
        return Result;
    }

    const handleGuardarPl = async () => {

        try {
            spinnerModalMostrar(true, 'Guardando');

            if (Datos.NombrePl.value.length > 0) {

                let _datos = {};
                _datos.Empresa = empresa;
                _datos.Tipo = Config.tpSimple;
                _datos.Nombre = Datos.NombrePl.value;
                _datos.Descripcion = Datos.DescripcionPl.value;
                _datos.Tipo_Asiento = selectedTipo.value;
                _datos.Aprobado = false;
                _datos.Comentario = Datos.DescripcionPl2.value;
                _datos.Recurrencia = false;
                _datos.Usuario_Modifica = usuario;

                let listaDetalle = [];
                let itemTemp = null;
                const listaTemp = listaDatos.filter(x => parseFloat(x.Debe) > 0 || parseFloat(x.Haber) > 0);

                for (let i = 0; i < listaTemp.length; i++) {
                    itemTemp = {};

                    if (Datos.DocPorLineaPl.value) {
                        itemTemp.Documento = listaTemp[i].Documento;
                    }

                    if (Datos.DescPorLineaPl.value) {
                        itemTemp.Descripcion = listaTemp[i].Referencia;
                    }

                    if (listaTemp[i].CuentaStr.trim() !== '' && listaTemp[i].Centro_CostoStr.trim() !== '') {

                        itemTemp.Plantilla = 0;
                        itemTemp.Linea = listaDetalle.length + 1;
                        itemTemp.Cuenta = listaTemp[i].Cuenta;

                        if (Datos.FechaPorLineaPl.value && listaTemp[i].Fecha !== '') {
                            itemTemp.Fecha = listaTemp[i].Fecha;
                        } else {
                            itemTemp.Fecha = null;
                        }

                        if (Datos.MontosPl.value) {
                            itemTemp.Debito = listaTemp[i].Debe;
                            itemTemp.Credito = listaTemp[i].Haber;
                        }

                        itemTemp.Centro_Costo = listaTemp[i].Centro_Costo;

                        listaDetalle.push(itemTemp);

                    }

                }

                const response = await EncaPlantillas_Guardar_Request(token, _datos, listaDetalle);

                if (response.Exitoso) {
                    Notificacion.success('Se guardó la plantilla exitosamente.');
                    setSelectModalPl(false);
                } else {
                    Notificacion.error(`Error: ${response.Mensaje}`);
                }
            } else {
                Notificacion.error('Error: Debe definir un Nombre para la plantilla.');
            }
        } catch (ex) {
            Notificacion.error(ex.message);
        } finally {
            spinnerModalMostrar(false, '', 3);
        }

    }

    const handleCerrarModalPl = () => {
        setSelectModalPl(false);
    };

    const handleCerrarModalBi = () => {
        setSelectModalBi(false);
    };

    const handleCheckBox = (event) => {
        const name = event.target.name;
        const value = event.target.checked;
        let newAttributes = Datos[name].attributes;

        let _Datos = Object.assign({}, Datos, {
            [name]: { value: value, attributes: newAttributes },
        });

        if (name === 'DescripcionPlCk' && value) {
            _Datos.DescripcionPl2.attributes.readOnly = true;
        } else if (name === 'DescripcionPlCk') {
            _Datos.DescripcionPl2.attributes.readOnly = false;
        }

        setDatos(_Datos);
    };

    const cargarDatosPlantilla = () => {

        let _Datos = { ...Datos };

        setSelectModalPl(true);
        _Datos.NombrePl.value = '';
        _Datos.DescripcionPl.value = '';
        _Datos.DescripcionPl2.value = _Datos.Descripcion.value;
        _Datos.TipoPl.value = true;
        _Datos.DescripcionPlCk.value = true;
        _Datos.MontosPl.value = true;
        _Datos.DocPorLineaPl.value = true;
        _Datos.DescPorLineaPl.value = true;
        _Datos.FechaPorLineaPl.value = true;

        setDatos(_Datos);

    }

    const handleModalPl = () => {

        const optSegopt = optSeg.TOpciones_Menu;

        const Errores = hayErroresLinea(true);

        if (Errores.length > 0) {
            Notificacion.error(Errores);
        } else {
            let validar = validarMenuOpcion(optSegopt.Plantilla.value);
            if (!validar) {
                cargarDatosPlantilla();
            }
        }
    }

    const handleBitacora = async () => {
        if (id === 0) {
            Notificacion.error('No hay bitácora para este registro.');
        } else {

            let _Datos = { ...Datos };

            _Datos.AsientoBi.value = `${selectedTipo.label} - ${asiento.Numero.toString().padStart(5, '0')}`;
            _Datos.DigitadoPorBi.value = asiento.DigitadoX;
            _Datos.NombreDigitadoBi.value = asiento.DigitadoXNombre;
            _Datos.AprobadoPorBi.value = asiento.AprobadoX;
            _Datos.NombreAprobadoBi.value = asiento.AprobadoXNombre;
            _Datos.AplicadoPorBi.value = asiento.AplicadoX;
            _Datos.AplicadoPorBi.value = asiento.AplicadoXNombre;
            _Datos.AnuladoPorBi.value = asiento.AnuladoX;
            _Datos.NombreAnuladoBi.value = asiento.AnuladoXNombre;
            _Datos.ModificadoPorBi.value = asiento.Modificado;
            _Datos.NombreModificadoBi.value = asiento.ModificadoNombre;
            _Datos.ReversadoPorBi.value = asiento.Reversado;
            _Datos.UltimaActualizacionBi.value = asiento.Fecha_Actualizacion;

            setDatos(_Datos);
            setSelectModalBi(true);

        }
    }

    return (<Fragment>
        <MantAsientoInt
            titulo={id === 0 ? 'Agregar Asiento' : 'Modificar Asiento'}
            botones={id === 0 ? botones : botonesModif}
            handleSelectedTipo={handleSelectedTipo}
            selectedTipo={selectedTipo}
            listaTipo={listaTipo}
            onhandleSelectedOptionMes={onhandleSelectedOptionMes}
            selectedOptionMes={selectedOptionMes}
            listaMeses={listaMeses}
            onhandleAnioChange={onhandleAnioChange}
            validarAnio={validarAnio}
            validarSoloNumeros={validarSoloNumeros}
            Datos={Datos}
            onChangeInput={onChangeInput}
            listaDatos={listaDatos}
            columnas={columnas}
            selectRow={selectRow}
            cellEdit={cellEdit}
            actTabla={actTabla}
            rowStyleLista={rowStyleLista}
            pColumn={pColumn}
        />
        <BotonArriba Delay={10} Visible={100} />
        <ModalSpinner
            selectedModal={SpinnerModal.mostrar}
            contentLabel={'spinnerModalProgress'}
            label={SpinnerModal.texto}
            tipoSpinner={SpinnerModal.tipo}
        />
        <ModalSeguridad
            modalTitle={'Requiere Permisos'}
            menuId={menuId}
            opcionId={opcionValidar}
            show={showModalSeguridad}
            onActionResult={onActionResultModal}
            onHide={handleCerrarModal}
        />
        <ModalBusqueda
            selectedModal={selectModal}
            contentLabel={'selectedBusquedas'}
            listaFiltro={listCentroCostoFiltro}
            columnas={Header}
            keyRow={'ID'}
            label={'Lista de Centros de Costos Asociados'}
            onSelectedRow={onRowSelectBusqueda}
            handleChangeSearch={handleChangeSearch}
            cerrarModal={cerrarModal}
            seleccionModal={seleccionModal}
            rowsSelected={rowsSelected}
        />
        <ModalBusquedaTree
            selectedModal={selectModalTree}
            contentLabel={'selectedBusquedasTree'}
            label={'Catálogo'}
            onSelectedRow={onRowSelectBusquedaTree}
            cerrarModal={cerrarModalTree}
            seleccionModal={seleccionModalTree}
            maxDepth={5}
            carga_ListTree={() => { }}
            listatree={listCuentasCont}
        />
        <ModalPlantilla
            contentLabel={''}
            Datos={Datos}
            cerrarModal={handleCerrarModalPl}
            onChangeInput={onChangeInput}
            handleGuardar={handleGuardarPl}
            showModal={selectModalPl}
            handleCheckBox={handleCheckBox}
        />
        <ModalBitacora
            contentLabel={''}
            Datos={Datos}
            cerrarModal={handleCerrarModalBi}
            showModal={selectModalBi}
        />
        <ModalMontoPorc
            contentLabel={''}
            Datos={Datos}
            cerrarModal={handleCerrarModalMontoPorc}
            showModal={selectModalMontoPorc}
            handleGuardar={handleAceptarMontoPorc}
            onChangeInputPorMonto={onChangeInputPorMonto}
            onChangeEditar={onChangeEditar}
            onFormato={onFormato}
        />
    </Fragment>)

}
export default withRouter(memo(MantAsiento));