Imports System.Text
Imports tsl5.Extensiones
Imports tsl5.Extensiones.StringExtensions
Namespace Bancos
    'Namespace AEB_19
    '    Public Class DatosFichero
    '        Property FechaSoporte As Date
    '        Property FechaCargo As Date
    '        Property Presentador As New DatosPresentador
    '        Property Ordenantes As New List(Of DatosOrdenante)
    '    End Class
    '    Public Class DatosPresentador
    '        Property Nombre As String
    '        Property NIF As String
    '        Property EntidadReceptora As String
    '        Property Oficina As String
    '    End Class
    '    Public Class DatosOrdenante
    '        Property Nombre As String
    '        Property NIF As String
    '        Property CuentaAbono As New CuentaBancaria
    '        Property Procedimiento As String
    '        Property DatosRecibo As New List(Of DatosRecibo)
    '    End Class
    '    Public Class DatosRecibo
    '        Property NIF_Cliente As String
    '        Property CodigoReferencia As String
    '        Property NombreTitularDomiciliacion As String
    '        Property CuentaAdeudo As New CuentaBancaria
    '        Property Importe As Double
    '        Property Conceptos As String()
    '        Property CamposOpcionales As New CamposOpcionales
    '    End Class
    '    Public Class CamposOpcionales
    '        Property NombreTitularCuenta As String
    '        Property DomicilioTitularCuenta As String
    '        Property PlazaDomicilioTitularCuenta As String
    '        Property CodigoPostalTitularCuenta As String
    '    End Class
    '    Public Class CuentaBancaria
    '        Property Entidad As String
    '        Property Oficina As String
    '        Property DC As String
    '        Property NumeroCuenta As String
    '    End Class
    '    Public Class Utilidades
    '        Public Shared Sub GeneraFichero(Datos As DatosFichero, Fichero As String, Optional ByVal Sobreescribir As Boolean = False)
    '            If Sobreescribir Then
    '                If IO.File.Exists(Fichero) Then IO.File.Delete(Fichero)
    '            Else
    '                If IO.File.Exists(Fichero) Then Throw New Exception("Fichero " & Fichero & " existente")
    '            End If            
    '            Dim fs As New IO.FileStream(Fichero, IO.FileMode.CreateNew)
    '            GeneraFichero(Datos, fs)
    '            fs.Close()
    '        End Sub
    '        Public Shared Sub GeneraFichero(Datos As DatosFichero, ByRef st As IO.Stream)
    '            '        CompruebaDatos(Datos)
    '            Try
    '                Dim Registro As String
    '                '  Dim ms As New IO.MemoryStream
    '                Dim sw As New IO.StreamWriter(st, System.Text.Encoding.GetEncoding("iso-8859-1"))

    '                Dim iNumRegOrdenante, iNumRegPresentador As Integer

    '                ' REGISTRO DE CABECERA 1 (PRESENTADOR)

    '                Registro = "51"
    '                Registro &= "80"
    '                Registro &= Datos.Presentador.NIF.Substring(0, Math.Min(Datos.Presentador.NIF.Length, 9)).PadLeft(9, "0")
    '                Registro &= "".PadLeft(3, " ")
    '                Registro &= FechaAEB(Datos.FechaSoporte)
    '                Registro &= "".PadLeft(6, " ")
    '                Registro &= Datos.Presentador.Nombre.Substring(0, Math.Min(Datos.Presentador.Nombre.Length, 40)).PadRight(40, " ")
    '                Registro &= "".PadLeft(20, " ")
    '                Registro &= Datos.Presentador.EntidadReceptora
    '                Registro &= Datos.Presentador.Oficina
    '                Registro &= "".PadRight(12, " ")
    '                Registro &= "".PadRight(40, " ")
    '                Registro &= "".PadRight(14, " ")
    '                iNumRegPresentador += 1
    '                sw.WriteLine(Registro)

    '                ' REGISTRO DE CABECERA 2 (ORDENANTE)
    '                Dim ordenante As tsl5.Bancos.AEB_19.DatosOrdenante

    '                Dim dTotalOrd, dTotalGen As Double

    '                For Each ordenante In Datos.Ordenantes
    '                    iNumRegOrdenante = 0
    '                    dTotalOrd = 0
    '                    Registro = "53"
    '                    Registro &= "80"
    '                    Registro &= ordenante.NIF.Substring(0, Math.Min(ordenante.NIF.Length, 9)).PadLeft(9, "0")
    '                    Registro &= "".PadLeft(3, " ")
    '                    Registro &= FechaAEB(Datos.FechaSoporte)
    '                    Registro &= FechaAEB(Datos.FechaCargo)
    '                    Registro &= ordenante.Nombre.Substring(0, Math.Min(ordenante.Nombre.Length, 40)).PadRight(40, " ")
    '                    Registro &= "".PadLeft(20, " ")
    '                    Registro &= ordenante.CuentaAbono.Entidad
    '                    Registro &= ordenante.CuentaAbono.Oficina
    '                    Registro &= ordenante.CuentaAbono.DC
    '                    Registro &= ordenante.CuentaAbono.NumeroCuenta
    '                    Registro &= "".PadRight(8, " ")
    '                    Registro &= ordenante.Procedimiento
    '                    Registro &= "".PadRight(10, " ")
    '                    Registro &= "".PadRight(40, " ")
    '                    Registro &= "".PadRight(14, " ")
    '                    iNumRegOrdenante += 1
    '                    sw.WriteLine(Registro)

    '                    Dim dr As tsl5.Bancos.AEB_19.DatosRecibo
    '                    For Each dr In ordenante.DatosRecibo
    '                        ' REGISTRO INDIVIDUAL OBLIGATORIO

    '                        Registro = "56"
    '                        Registro &= "80"
    '                        Registro &= ordenante.NIF.PadLeft(9, "0")
    '                        Registro &= "".PadLeft(3, " ")
    '                        Registro &= dr.CodigoReferencia.PadRight(12, " ")
    '                        Registro &= dr.NombreTitularDomiciliacion.Substring(0, Math.Min(dr.NombreTitularDomiciliacion.Length, 40)).PadRight(40, " ")
    '                        Registro &= dr.CuentaAdeudo.Entidad.PadLeft(4, "0")
    '                        Registro &= dr.CuentaAdeudo.Oficina.PadLeft(4, "0")
    '                        Registro &= dr.CuentaAdeudo.DC.PadLeft(2, "0")
    '                        Registro &= dr.CuentaAdeudo.NumeroCuenta.PadLeft(10, "0")
    '                        Registro &= (Math.Round(dr.Importe, 2) * 100).ToString.PadLeft(10, "0")
    '                        dTotalOrd += Math.Round(dr.Importe, 2)
    '                        Registro &= "".PadRight(6, " ")
    '                        Registro &= "".PadRight(10, " ")
    '                        Registro &= dr.Conceptos(0).Substring(0, Math.Min(dr.Conceptos(0).Length, 40)).PadRight(40, " ")
    '                        Registro &= "".PadRight(8, " ")
    '                        iNumRegOrdenante += 1
    '                        sw.WriteLine(Registro)
    '                        ' REGISTROS INDIVIDUALES OPCIONALES (DEL 1 AL 5)
    '                        For i = 1 To 15 Step 3
    '                            If dr.Conceptos.Length >= i + 1 Then
    '                                Registro = "56"
    '                                Registro &= (81 + (i \ 3)).ToString
    '                                Registro &= ordenante.NIF.Substring(0, Math.Min(ordenante.NIF.Length, 9)).PadLeft(9, "0")
    '                                Registro &= "".PadLeft(3, " ")
    '                                Registro &= dr.CodigoReferencia.PadRight(12, " ")
    '                                Registro &= dr.Conceptos(i).Substring(0, Math.Min(dr.Conceptos(i).Length, 40)).PadRight(40, " ")
    '                                If dr.Conceptos.Length >= i + 2 Then
    '                                    Registro &= dr.Conceptos(i + 1).Substring(0, Math.Min(dr.Conceptos(i + 1).Length, 40)).PadRight(40, " ")
    '                                    If dr.Conceptos.Length >= i + 3 Then
    '                                        Registro &= dr.Conceptos(i + 2).Substring(0, Math.Min(dr.Conceptos(i + 2).Length, 40)).PadRight(40, " ")
    '                                    Else
    '                                        Registro &= "".PadRight(40, " ")
    '                                    End If
    '                                Else
    '                                    Registro &= "".PadRight(40, " ")
    '                                    Registro &= "".PadRight(40, " ")
    '                                End If
    '                                Registro &= "".PadRight(14, " ")
    '                                iNumRegOrdenante += 1
    '                                sw.WriteLine(Registro)
    '                            Else
    '                                Exit For
    '                            End If
    '                        Next
    '                        ' REGISTRO OPCIONAL 6º
    '                        If dr.CamposOpcionales.NombreTitularCuenta <> "" Or dr.CamposOpcionales.DomicilioTitularCuenta <> "" Or dr.CamposOpcionales.PlazaDomicilioTitularCuenta <> "" Or dr.CamposOpcionales.CodigoPostalTitularCuenta <> "" Then
    '                            Registro = "56"
    '                            Registro &= "86"
    '                            Registro &= ordenante.NIF.PadLeft(9, "0")
    '                            Registro &= "".PadLeft(3, " ")
    '                            Registro &= dr.CodigoReferencia.PadRight(12, " ")
    '                            Registro &= dr.CamposOpcionales.NombreTitularCuenta.Substring(0, Math.Min(dr.CamposOpcionales.NombreTitularCuenta.Length, 40)).PadRight(40, " ")
    '                            Registro &= dr.CamposOpcionales.DomicilioTitularCuenta.Substring(0, Math.Min(dr.CamposOpcionales.DomicilioTitularCuenta.Length, 40)).PadRight(40, " ")
    '                            Registro &= dr.CamposOpcionales.PlazaDomicilioTitularCuenta.Substring(0, Math.Min(dr.CamposOpcionales.PlazaDomicilioTitularCuenta.Length, 35)).PadRight(35, " ")
    '                            Registro &= dr.CamposOpcionales.CodigoPostalTitularCuenta.Substring(0, Math.Min(dr.CamposOpcionales.CodigoPostalTitularCuenta.Length, 5)).PadRight(5, " ")
    '                            Registro &= "".PadRight(14, " ")
    '                            iNumRegOrdenante += 1
    '                            sw.WriteLine(Registro)
    '                        End If
    '                    Next
    '                    ' REGISTRO TOTAL DE ORDENANTE

    '                    Registro = "58"
    '                    Registro &= "80"
    '                    Registro &= Datos.Presentador.NIF.PadLeft(9, "0")
    '                    Registro &= "".PadLeft(3, " ")
    '                    Registro &= "".PadLeft(12, " ")
    '                    Registro &= "".PadLeft(40, " ")
    '                    Registro &= "".PadLeft(20, " ")
    '                    Registro &= (Math.Round(dTotalOrd, 2) * 100).ToString.PadLeft(10, "0")
    '                    Registro &= "".PadLeft(6, " ")
    '                    Registro &= ordenante.DatosRecibo.Count.ToString.PadLeft(10, "0")
    '                    iNumRegOrdenante += 1
    '                    Registro &= (iNumRegOrdenante).ToString.PadLeft(10, "0")
    '                    Registro &= "".PadLeft(20, " ")
    '                    Registro &= "".PadLeft(18, " ")
    '                    sw.WriteLine(Registro)
    '                    iNumRegPresentador += iNumRegOrdenante
    '                    dTotalGen += dTotalOrd
    '                Next
    '                ' REGISTRO DE CABECERA 2 (PRESENTADOR)

    '                Registro = "58"
    '                Registro &= "80"
    '                Registro &= Datos.Presentador.NIF.PadLeft(9, "0")
    '                Registro &= "".PadLeft(3, " ")
    '                Registro &= "".PadLeft(12, " ")
    '                Registro &= "".PadLeft(40, " ")

    '                Registro &= "".PadLeft(20, " ")
    '                Registro &= (dTotalGen * 100).ToString.PadLeft(10, "0")
    '                Registro &= "".PadLeft(6, " ")
    '                Registro &= Datos.Ordenantes.Count.ToString.PadLeft(10, "0")
    '                iNumRegPresentador += 1
    '                Registro &= (iNumRegPresentador).ToString.PadLeft(10, "0")
    '                Registro &= "".PadLeft(20, " ")
    '                Registro &= "".PadLeft(18, " ")
    '                sw.WriteLine(Registro)
    '                sw.Close()
    '                st.Close()
    '            Catch ex As Exception
    '                Throw ex
    '            End Try
    '        End Sub
    '        Public Shared Function FechaAEB(Fecha As Date) As String
    '            Return Fecha.Day.ToString.PadLeft(2, "0") & Fecha.Month.ToString.PadLeft(2, "0") & (Fecha.Year Mod 100).ToString.PadLeft(2, "0")
    '        End Function
    '    End Class
    'End Namespace
    Public Enum TiposAdeudosEnum
        ''' <summary>
        ''' Último pago
        ''' </summary>
        ''' <remarks></remarks>
        FNAL
        ''' <summary>
        ''' Primer pago
        ''' </summary>
        ''' <remarks></remarks>
        FRST
        ''' <summary>
        ''' Pago Único
        ''' </summary>
        ''' <remarks></remarks>
        OOFF
        ''' <summary>
        ''' Pago Recurrente
        ''' </summary>
        ''' <remarks></remarks>
        RCUR
    End Enum

    ''' <summary>
    ''' Overall description
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum CategoriaPropositoEnum
        ''' <summary>
        ''' Transferencia de gestión de efectivo. La transacción es una instrucción general de gestión de efectivo
        ''' </summary>
        ''' <remarks></remarks>
        CASH
        ''' <summary>
        ''' Pago de Tarjeta de Crédito. La transacción está relacionada con un pago de tarjeta de crédito. 
        ''' </summary>
        ''' <remarks></remarks>
        CCRD
        ''' <summary>
        ''' Pago de liquidación de operaciones. La transacción está realizada con la liquidación de una operación.Por ejemplo: una operación de compraventa de divisa o una operación de valores.
        ''' </summary>
        ''' <remarks></remarks>
        CORT
        ''' <summary>
        ''' Pago de Tarjeta de Débito. La transacción está relacionada con un pago de tarjeta de débito. 
        ''' </summary>
        ''' <remarks></remarks>
        DCRD
        ''' <summary>
        ''' Dividendos. La transacción es el pago de dividendos. 
        ''' </summary>
        ''' <remarks></remarks>
        DIVI
        ''' <summary>
        ''' Pago de la administración. La transacción es el pago a o de un departamento de la administración pública.
        ''' </summary>
        ''' <remarks></remarks>
        GOVT
        ''' <summary>
        ''' Cobertura. La transacción está relacionada con el pago de una operación de cobertura. 
        ''' </summary>
        ''' <remarks></remarks>

        HEDG
        ''' <summary>
        ''' Pago de tarjeta de crédito irrevocable. La transacción es un reembolso de un pago de tarjeta de crédito. 
        ''' </summary>
        ''' <remarks></remarks>

        ICCP
        ''' <summary>
        ''' Pago de tarjeta de débito irrevocable. La transacción es un reembolso de un pago de tarjeta de débito. 
        ''' </summary>
        ''' <remarks></remarks>
        IDCP
        ''' <summary>
        ''' Pago intra-compañía. La transacción es un pago intra-compañía. Por ejemplo: un pago entre dos compañías pertenecientes a un mismo grupo. 
        ''' </summary>
        ''' <remarks></remarks>
        INTC
        ''' <summary>
        ''' Intereses. La transacción es un pago de intereses. 
        ''' </summary>
        ''' <remarks></remarks>
        INTE
        ''' <summary>
        '''Préstamos. La transacción está relacionada con la transferencia de un préstamo a un prestatario. 
        ''' </summary>
        ''' <remarks></remarks>
        LOAN
        ''' <summary>
        ''' Pago de pensión. La transacción es el pago de una pensión
        ''' </summary>
        ''' <remarks></remarks>
        PENS
        ''' <summary>
        ''' Nóminas. La transacción es el pago de nóminas.
        ''' </summary>
        ''' <remarks></remarks>
        SALA
        ''' <summary>
        ''' Valores. La transacción es el pago de valores. 
        ''' </summary>
        ''' <remarks></remarks>
        SECU
        ''' <summary>
        ''' Valores. La transacción es el pago de valores. 
        ''' </summary>
        ''' <remarks></remarks>
        SSBE
        ''' <summary>
        ''' Pago de asistencia a Seguridad Social. La transacción es de una asistencia de S.S. Por ejemplo: el pago hecho por la S.S. para el mantenimiento de individuos.
        ''' </summary>
        ''' <remarks></remarks>
        SUPP
        ''' <summary>
        ''' Pago de impuestos. La transacción está relacionada con el pago de impuestos.
        ''' </summary>
        ''' <remarks></remarks>
        TAXS
        ''' <summary>
        ''' Comercio. La transacción está relacionada con el pago de una transacción comercial. 
        ''' </summary>
        ''' <remarks></remarks>
        TRAD
        ''' <summary>
        ''' Pago de tesorería. La transacción está relacionada con operaciones de tesorería. 
        ''' </summary>
        ''' <remarks></remarks>
        TREA
        ''' <summary>
        ''' IVA. La transacción es el pago del IVA. 
        ''' </summary>
        ''' <remarks></remarks>
        VATX
        ''' <summary>
        ''' Retenciones. La transacción está relacionada con el pago de retenciones (impuestos) 
        ''' </summary>
        ''' <remarks></remarks>
        WHLD
    End Enum
    Public Class Genericas

        Public Shared Function CalcularDigitoControlBancario(Banco As Integer, Oficina As Integer, Cuenta As Double) As String
            Dim sBank As String
            Dim sSubBank As String
            Dim sAccount As String
            Dim Temporal As Integer

            sBank = Format(Banco, "0000")
            sSubBank = Format(Oficina, "0000")
            sAccount = Format(Cuenta, "0000000000")

            Temporal = 0
            Temporal = Temporal + Mid(sBank, 1, 1) * 4
            Temporal = Temporal + Mid(sBank, 2, 1) * 8
            Temporal = Temporal + Mid(sBank, 3, 1) * 5
            Temporal = Temporal + Mid(sBank, 4, 1) * 10
            Temporal = Temporal + Mid(sSubBank, 1, 1) * 9
            Temporal = Temporal + Mid(sSubBank, 2, 1) * 7
            Temporal = Temporal + Mid(sSubBank, 3, 1) * 3
            Temporal = Temporal + Mid(sSubBank, 4, 1) * 6
            Temporal = 11 - (Temporal Mod 11)
            If Temporal = 11 Then
                CalcularDigitoControlBancario = "0"
            ElseIf Temporal = 10 Then
                CalcularDigitoControlBancario = "1"
            Else
                CalcularDigitoControlBancario = Format(Temporal, "0")
            End If

            Temporal = 0
            Temporal = Temporal + Mid(sAccount, 1, 1) * 1
            Temporal = Temporal + Mid(sAccount, 2, 1) * 2
            Temporal = Temporal + Mid(sAccount, 3, 1) * 4
            Temporal = Temporal + Mid(sAccount, 4, 1) * 8
            Temporal = Temporal + Mid(sAccount, 5, 1) * 5
            Temporal = Temporal + Mid(sAccount, 6, 1) * 10
            Temporal = Temporal + Mid(sAccount, 7, 1) * 9
            Temporal = Temporal + Mid(sAccount, 8, 1) * 7
            Temporal = Temporal + Mid(sAccount, 9, 1) * 3
            Temporal = Temporal + Mid(sAccount, 10, 1) * 6
            Temporal = 11 - (Temporal Mod 11)
            If Temporal = 11 Then
                CalcularDigitoControlBancario = CalcularDigitoControlBancario + "0"
            ElseIf Temporal = 10 Then
                CalcularDigitoControlBancario = CalcularDigitoControlBancario + "1"
            Else
                CalcularDigitoControlBancario = CalcularDigitoControlBancario + Format(Temporal, "0")
            End If
        End Function

        Public Shared Function IBANCorrecto(IBAN As String) As Boolean
            'Try
            '    If IBAN.NothingAVacio.Length <> 24 Then
            '        Return False
            '    Else
            '        Dim CodigoPais As String = IBAN.Substring(0, 2)
            '        Dim CodigoBanco As String = IBAN.Substring(4, 4)
            '        Dim CodigoOficina As String = IBAN.Substring(8, 4)
            '        Dim DigitoControl As String = IBAN.Substring(12, 2)
            '        Dim Cuenta As String = IBAN.Substring(14, 10)
            '        Dim sIBAN = CalcularIBAN(CodigoPais, CodigoBanco, CodigoOficina, DigitoControl, Cuenta)
            '        Return sIBAN = IBAN
            '    End If
            'Catch ex As Exception
            '    Return False
            'End Try
            If IBAN.NothingAVacio <> "" Then
                IBAN = IBAN.Replace(" ", "")
                Dim validator As New IbanNet.IbanValidator
                Return validator.Validate(IBAN).IsValid
            Else
                Return False
            End If
        End Function
        Public Shared Function CalcularIBAN(ByVal CodigoPais As String,
                                  ByVal CodigoBanco As String,
                                  ByVal CodigoOficina As String,
                                  ByVal DigitoControl As String,
                                  ByVal Cuenta As String) As String

            Dim s1 As String = CodigoBanco + CodigoOficina + DigitoControl + Cuenta + CodigoPais + "00", s2 As String = ""

            'Substitute letters
            For i As Integer = 0 To s1.Length - 1
                If IsNumeric(s1.Substring(i, 1)) = True Then
                    s2 += s1.Substring(i, 1)
                Else
                    s2 += Convert.ToString(Asc(s1.Substring(i, 1)) - 55).PadLeft(2, "0")
                End If
            Next

            'Return the IBAN
            Return CodigoPais + MOD_97_10(s2) + CodigoBanco + CodigoOficina + DigitoControl + Cuenta
        End Function
        Public Shared Function CalcularIBAN_ES(ByVal CCC As String) As String
            Return CalcularIBAN("ES", CCC.Split("-")(0), CCC.Split("-")(1), CCC.Split("-")(2), CCC.Split("-")(3))
        End Function

        Public Shared Function CalcularIdentificadorSEPA(ByVal CIF As String, Optional CodigoPais As String = "ES", Optional Sufijo As String = "000") As String
            Try
                Dim s As String = CIF.Trim & CodigoPais & "00"
                Dim sResultado As String = ""
                Dim c As Char
                For Each c In s
                    If Char.IsNumber(c) Then
                        sResultado &= c.ToString
                    Else
                        sResultado &= (Asc(c) - 55).ToString
                    End If
                Next
                Return CodigoPais & MOD_97_10(sResultado) & Sufijo & CIF
            Catch ex As Exception
                Throw New Exception(ex.Message, ex)
            End Try
        End Function
        Private Shared Function MOD_97_10(ByVal s As String) As String

            Dim s1 As String, s2 As String
            Dim l1 As Integer, l2 As Integer

            s1 = s.Substring(0, 9)
            s2 = s.Substring(s1.Length)
            l1 = Convert.ToInt32(s1)
            l2 = l1 Mod 97

            While s2 <> ""
                If Len(s2) > 7 Then
                    s1 = Convert.ToString(l2).PadLeft(2, "0") + s2.Substring(0, 7)
                    s2 = s2.Substring(7)
                Else
                    s1 = Convert.ToString(l2).PadLeft(2, "0") + s2
                    s2 = ""
                End If
                l1 = Convert.ToInt32(s1)
                l2 = l1 Mod 97
            End While

            Return Convert.ToString(98 - l2).PadLeft(2, "0")

        End Function


    End Class
    Namespace SEPA
        Public Class DatosFichero
            Property FechaSoporte As DateTime
            Property FechaCargo As Date
            Property Presentador As New DatosPresentador
            Property Acreedores As New List(Of DatosAcreedor)
            Property ReferenciaIdentificativa As String


        End Class
        Public Class DatosPresentador
            Property Nombre As String
            Property NIF As String
            Property Sufijo As String
            Property EntidadReceptora As String
            Property Oficina As String

            Property DOMICILIO As String

            Property NUMERO As String

            Property CPO As String

            Property CIUDAD As String

            Property PAIS As String



        End Class
        Public Class DatosAcreedor
            Property Nombre As String
            Property NIF As String
            Property Sufijo As String
            Property CuentaAbono As New CuentaBancaria
            Property Procedimiento As String
            Property FechaCobro As DateTime
            Property Direccion As String
            Property CodigoPostal As String
            Property Municipio As String
            Property Provincia As String
            Property CodigoPais As String

            Property DatosRecibo As New List(Of DatosRecibo)

            Property Libre1 As String

            Property Libre2 As String

            Property DOMICILIO As String

            Property NUMERO As String

            Property CPO As String

            Property CIUDAD As String

            Property PAIS As String



        End Class
        Public Class DatosRecibo
            Property CodigoReferencia As String
            Property CodigoReferenciaMandato As String
            Property FechaMandato As Date

            Property NombreDeudor As String
            Property DireccionDeudor1 As String
            Property DireccionDeudor2 As String
            Property DireccionDeudor3 As String
            Property CodigoPaisDeudor As String
            Property TipoIdentificacionDeudor As String
            Property IdentificacionDeudor As String
            Property IdentificacionDeudorEmisorCodigo As String
            Property CuentaAdeudo As New CuentaBancaria
            Property TipoAdeudo As TiposAdeudosEnum
            Property CategoriaProposito As CategoriaPropositoEnum
            Property Importe As Double
            Property CamposOpcionales As New CamposOpcionales
            Property PropositoAdeudo As String
            Property Concepto As String
            Property Libre As String
            Property NombreUltimoAcreedor As String
            Property TipoIdentificacionUltimoAcreedor As String 'Campo 7 Opcional 2
            Property IdentificacionUltimoAcreedor As String 'campo 8 opcional 2
            Property IdentificacionUltimoAcreedorEmisorCodigo As String 'CAMPO 9 Opcional 2
            Property NombreTitularDomiciliacion As String 'CAMPO 10 Opcional 2
            Property TITitularDomiciliacion As String 'CAMPO 11 Opcional 2
            Property IdentificacionTitularDomiciliacion As String 'CAMPO 12 Opcional 2
            Property IdentificacionTitularDomiciliacionEmisorCodigo As String ' CAMPO 13 Opcional 2
            Property Libre2 As String ' CAMPO 14 Opcional 2

        End Class
        Public Class CamposOpcionales
            Property NombreTitularCuenta As String
            Property DomicilioTitularCuenta As String
            Property PlazaDomicilioTitularCuenta As String
            Property CodigoPostalTitularCuenta As String
        End Class
        Public Class CuentaBancaria
            Property BIC As String
            Property IBAN As String
            ReadOnly Property EntidadBancariaEspaña As String
                Get
                    If IBAN.NothingAVacio.Length = 24 AndAlso IBAN.Substring(0, 2) = "ES" Then
                        Return IBAN.Substring(4, 4)
                    Else
                        Return ""
                    End If
                End Get
            End Property
        End Class
        Public Class Utilidades
            Public Shared Sub GeneraFichero(Datos As DatosFichero, Fichero As String, Optional ByVal Sobreescribir As Boolean = False)
                If Sobreescribir Then
                    If IO.File.Exists(Fichero) Then IO.File.Delete(Fichero)
                Else
                    If IO.File.Exists(Fichero) Then Throw New Exception("Fichero " & Fichero & " existente")
                End If
                Dim fs As New IO.FileStream(Fichero, IO.FileMode.CreateNew)
                GeneraFichero19_14(Datos, fs)
                fs.Close()
            End Sub
            Public Shared Sub GeneraFichero19_14(Datos As DatosFichero, ByRef st As IO.Stream)
                Try
                    Dim Registro As String
                    '  Dim ms As New IO.MemoryStream
                    Dim sw As New IO.StreamWriter(st, System.Text.Encoding.GetEncoding("iso-8859-1"))

                    'Dim iNumRegAcreedor , iNumRegPresentador As Integer

                    ' REGISTRO DE CABECERA 1 (PRESENTADOR)
                    Dim dTotalAcreedorFP, dTotalAcreedor, dTotalPresentador As Double
                    Dim iNumRegistrosAcreedorFP, iNumRegistrosAcreedor, iNumRegistrosPresentador As Integer
                    Dim iNumAdeudosAcreedorFP, iNumAdeudosAcreedor, iNumAdeudosPresentador As Integer
                    Registro = "01" ' CAMPO 1 
                    Registro &= "19154" ' CAMPO 2 'ANTES 19143
                    Registro &= "001" ' CAMPO 3
                    Registro &= Bancos.Genericas.CalcularIdentificadorSEPA(Datos.Presentador.NIF, , Datos.Presentador.Sufijo).PadRight(35, " ") ' CAMPO 4 
                    Registro &= Datos.Presentador.Nombre.ConvierteAAlfanumerico.PadRight(70, " ") ' CAMPO 5
                    Registro &= FechaSEPA(Datos.FechaSoporte) ' CAMPO 6
                    Registro &= "PRE" & FechaHoraSEPA(Now) & Datos.ReferenciaIdentificativa.PadRight(13, " ") ' CAMPO 7                     
                    Registro &= Datos.Presentador.EntidadReceptora.PadRight(4, " ") ' CAMPO 8
                    Registro &= Datos.Presentador.Oficina.PadRight(4, " ") ' CAMPO 9
                    Registro &= "".PadLeft(434, " ") ' CAMPO 10                    
                    sw.WriteLine(Registro)

                    ' REGISTRO DE CABECERA 2 (ACREEDOR)
                    Dim acreedor As New tsl5.Bancos.SEPA.DatosAcreedor

                    '  Dim dTotalOrd, dTotalGen As Double
                    '   Dim iTotalRegAcreedor As Integer

                    For Each acreedor In Datos.Acreedores
                        iNumAdeudosAcreedor = 0
                        iNumAdeudosAcreedorFP = 0
                        iNumRegistrosAcreedor = 1
                        iNumRegistrosAcreedorFP = 1


                        Registro = "02" ' CAMPO 1
                        Registro &= "19154" ' CAMPO 2 'ANTES 19143
                        Registro &= "002" ' CAMPO 3
                        Registro &= Bancos.Genericas.CalcularIdentificadorSEPA(acreedor.NIF, , acreedor.Sufijo).PadRight(35, " ") 'CAMPO 4
                        Registro &= FechaSEPA(acreedor.FechaCobro) 'CAMPO 5
                        Registro &= acreedor.Nombre.ConvierteAAlfanumerico.Substring(0, Math.Min(acreedor.Nombre.Length, 70)).PadRight(70, " ") 'CAMPO 6
                        Registro &= acreedor.Direccion.Substring(0, Math.Min(acreedor.Direccion.Length, 50)).PadRight(50, " ") ' CAMPO 7
                        Dim sCodPosMun As String = acreedor.CodigoPostal & " " & acreedor.Municipio
                        Registro &= sCodPosMun.Substring(0, Math.Min(sCodPosMun.Length, 50)).PadRight(50, " ") ' CAMPO 8
                        Registro &= acreedor.Provincia.Substring(0, Math.Min(acreedor.Provincia.Length, 40)).PadRight(40, " ") ' CAMPO 9
                        Registro &= acreedor.CodigoPais.Substring(0, Math.Min(acreedor.Provincia.Length, 2)).PadRight(2, " ") ' CAMPO 10
                        Registro &= acreedor.CuentaAbono.IBAN.PadRight(34, " ") ' CAMPO 11
                        Registro &= "".PadRight(301, " ") ' CAMPO 12
                        sw.WriteLine(Registro)
                        Dim dr As tsl5.Bancos.SEPA.DatosRecibo
                        For Each dr In acreedor.DatosRecibo
                            ' REGISTRO INDIVIDUAL OBLIGATORIO

                            iNumAdeudosAcreedor += 1
                            iNumAdeudosAcreedorFP += 1
                            iNumRegistrosAcreedor += 1
                            iNumRegistrosAcreedorFP += 1


                            Registro = "03" 'CAMPO 1
                            Registro &= "19154" ' CAMPO 2 'ANTES 19143
                            Registro &= "003" 'CAMPO 3
                            Registro &= dr.CodigoReferencia.Substring(0, Math.Min(dr.CodigoReferencia.Length, 35)).PadRight(35, " ") 'CAMPO 4
                            Registro &= dr.CodigoReferenciaMandato.Substring(0, Math.Min(dr.CodigoReferenciaMandato.Length, 35)).PadRight(35, " ") 'CAMPO 5
                            Registro &= dr.TipoAdeudo.ToString.PadRight(4, " ") 'CAMPO 6
                            Registro &= dr.CategoriaProposito.ToString.PadRight(4, " ") 'CAMPO 7
                            Registro &= (Math.Round(dr.Importe, 2, MidpointRounding.AwayFromZero) * 100).ToString.PadLeft(11, "0") 'CAMPO 8
                            Registro &= FechaSEPA(dr.FechaMandato) 'CAMPO 9
                            Registro &= dr.CuentaAdeudo.BIC.NothingAVacio.Substring(0, Math.Min(dr.CuentaAdeudo.BIC.NothingAVacio.Length, 11)).PadRight(11, " ") 'CAMPO 10
                            Registro &= dr.NombreDeudor.ConvierteAAlfanumerico.Substring(0, Math.Min(dr.NombreDeudor.Length, 70)).PadRight(70, " ") 'CAMPO 11
                            Registro &= dr.DireccionDeudor1.Substring(0, Math.Min(dr.DireccionDeudor1.Length, 50)).PadRight(50, " ") 'CAMPO 12
                            Registro &= dr.DireccionDeudor2.Substring(0, Math.Min(dr.DireccionDeudor2.Length, 50)).PadRight(50, " ") 'CAMPO 13
                            Registro &= dr.DireccionDeudor3.Substring(0, Math.Min(dr.DireccionDeudor3.Length, 40)).PadRight(40, " ") 'CAMPO 14
                            Registro &= dr.CodigoPaisDeudor.Substring(0, Math.Min(dr.CodigoPaisDeudor.Length, 2)).PadRight(2, " ") 'CAMPO 15
                            If dr.IdentificacionDeudor.Length > 0 Then
                                If "01234567890X".Contains(dr.IdentificacionDeudor.Substring(0, 1)) Then
                                    Registro &= dr.TipoIdentificacionDeudor.PadRight(1, "2") 'CAMPO 16
                                    dr.IdentificacionDeudor = "J" & dr.IdentificacionDeudor
                                Else
                                    Registro &= dr.TipoIdentificacionDeudor.PadRight(1, "1") 'CAMPO 16
                                    dr.IdentificacionDeudor = "I" & dr.IdentificacionDeudor
                                End If
                            Else
                                Registro &= dr.TipoIdentificacionDeudor.PadRight(1, " ") 'CAMPO 16
                            End If
                            Registro &= dr.IdentificacionDeudor.Substring(0, Math.Min(dr.IdentificacionDeudor.Length, 36)).PadRight(36, " ") 'CAMPO 17
                            Registro &= dr.IdentificacionDeudorEmisorCodigo.Substring(0, Math.Min(dr.IdentificacionDeudorEmisorCodigo.Length, 35)).PadRight(35, " ") 'CAMPO 18
                            Registro &= "A" 'dr.IdentificadorCuentaDeudor 'CAMPO 19
                            Dim sIBAN As String = dr.CuentaAdeudo.IBAN
                            Registro &= sIBAN.Substring(0, Math.Min(sIBAN.Length, 34)).PadRight(34, " ") 'CAMPO 20
                            Registro &= dr.PropositoAdeudo.Substring(0, Math.Min(dr.PropositoAdeudo.Length, 4)).PadRight(4, " ") 'CAMPO 21
                            Registro &= dr.Concepto.Substring(0, Math.Min(dr.Concepto.Length, 140)).PadRight(140, " ") 'CAMPO 22
                            Registro &= dr.Libre.Substring(0, Math.Min(dr.Libre.Length, 19)).PadRight(19, " ") 'CAMPO 23

                            dTotalAcreedorFP += Math.Round(dr.Importe, 2, MidpointRounding.AwayFromZero)
                            dTotalAcreedor += Math.Round(dr.Importe, 2, MidpointRounding.AwayFromZero)
                            sw.WriteLine(Registro)
                            If dr.NombreTitularDomiciliacion <> "" Then
                                Registro = "03" 'CAMPO 1
                                Registro &= "19154" ' CAMPO 2 'ANTES 19143
                                Registro &= "004" 'CAMPO 3
                                Registro &= dr.CodigoReferencia.Substring(0, Math.Min(dr.CodigoReferencia.Length, 35)).PadRight(35, " ") 'CAMPO 4
                                Registro &= dr.CodigoReferenciaMandato.Substring(0, Math.Min(dr.CodigoReferenciaMandato.Length, 35)).PadRight(35, " ") 'CAMPO 5
                                Registro &= dr.NombreUltimoAcreedor.ConvierteAAlfanumerico.Substring(0, Math.Min(dr.NombreUltimoAcreedor.Length, 70)).PadRight(70, " ") 'CAMPO 6
                                Registro &= dr.TipoIdentificacionUltimoAcreedor.PadRight(1, " ")  'CAMPO 7
                                Registro &= dr.IdentificacionUltimoAcreedor.Substring(0, Math.Min(dr.IdentificacionUltimoAcreedor.Length, 36)).PadRight(36, " ") 'CAMPO 8
                                Registro &= dr.IdentificacionUltimoAcreedorEmisorCodigo.Substring(0, Math.Min(dr.IdentificacionUltimoAcreedorEmisorCodigo.Length, 35)).PadRight(35, " ") 'CAMPO 9
                                Registro &= dr.NombreTitularDomiciliacion.ConvierteAAlfanumerico.Substring(0, Math.Min(dr.NombreTitularDomiciliacion.Length, 70)).PadRight(70, " ") 'CAMPO 10
                                Registro &= dr.TITitularDomiciliacion.PadRight(1, " ") 'CAMPO 11
                                Registro &= dr.IdentificacionTitularDomiciliacion.Substring(0, Math.Min(dr.IdentificacionTitularDomiciliacion.Length, 36)).PadRight(36, " ") 'CAMPO 12
                                Registro &= dr.IdentificacionTitularDomiciliacionEmisorCodigo.Substring(0, Math.Min(dr.IdentificacionTitularDomiciliacionEmisorCodigo.Length, 35)).PadRight(35, " ") 'CAMPO 13
                                Registro &= dr.Libre2.Substring(0, Math.Min(dr.Libre2.Length, 236)).PadRight(236, " ") 'CAMPO 14
                                iNumRegistrosAcreedor += 1
                                iNumRegistrosAcreedorFP += 1
                                sw.WriteLine(Registro)
                            End If
                        Next
                        ' REGISTRO TOTAL DE Acreedor por fechas de cobro
                        iNumRegistrosAcreedorFP += 1
                        Registro = "04" 'CAMPO 1
                        Registro &= Bancos.Genericas.CalcularIdentificadorSEPA(acreedor.NIF, , acreedor.Sufijo).PadRight(35, " ") 'CAMPO 2
                        Registro &= FechaSEPA(acreedor.FechaCobro) 'CAMPO 3
                        Registro &= (Math.Round(dTotalAcreedorFP, 2, MidpointRounding.AwayFromZero) * 100).ToString.PadLeft(17, "0") ' CAMPO 4 
                        Registro &= iNumAdeudosAcreedorFP.ToString.PadLeft(8, "0") 'CAMPO 4
                        Registro &= iNumRegistrosAcreedorFP.ToString.PadLeft(10, "0") 'CAMPO 5
                        Registro &= acreedor.Libre1.ToString.PadRight(520, " ") 'CAMPO 7
                        sw.WriteLine(Registro)
                        ' REGISTRO TOTAL DE Acreedor
                        iNumRegistrosAcreedor += 2 '1 más por el registro anterior fecha de pago
                        Registro = "05" 'CAMPO 1
                        Registro &= Bancos.Genericas.CalcularIdentificadorSEPA(acreedor.NIF, , acreedor.Sufijo).PadRight(35, " ") 'CAMPO 2                       
                        Registro &= (Math.Round(dTotalAcreedor, 2, MidpointRounding.AwayFromZero) * 100).ToString.PadLeft(17, "0") 'CAMPO 3
                        Registro &= iNumAdeudosAcreedor.ToString.PadLeft(8, "0") 'CAMPO 4
                        Registro &= iNumRegistrosAcreedor.ToString.PadLeft(10, "0") 'CAMPO 5
                        Registro &= acreedor.Libre2.ToString.PadRight(528, " ") 'CAMPO 6
                        sw.WriteLine(Registro)
                        iNumAdeudosPresentador += iNumAdeudosAcreedor
                        iNumRegistrosPresentador += iNumRegistrosAcreedor
                        dTotalPresentador += dTotalAcreedor
                    Next

                    ' REGISTRO TOTALES 
                    iNumRegistrosPresentador += 2 'cabecera y total
                    Registro = "99"
                    Registro &= (Math.Round(dTotalPresentador, 2, MidpointRounding.AwayFromZero) * 100).ToString.PadLeft(17, "0")
                    Registro &= iNumAdeudosPresentador.ToString.PadLeft(8, "0")
                    Registro &= iNumRegistrosPresentador.ToString.PadLeft(10, "0")
                    Registro &= acreedor.Libre2.ToString.PadRight(563, " ") 'CAMPO 6
                    sw.WriteLine(Registro)
                    sw.Close()
                    st.Close()
                Catch ex As Exception
                    Throw New Exception(ex.Message, ex)
                End Try
            End Sub

            Public Shared Function FechaSEPA(Fecha As Date) As String
                Return Fecha.Year.ToString & Fecha.Month.ToString.PadLeft(2, "0") & Fecha.Day.ToString.PadLeft(2, "0")
            End Function
            Public Shared Function FechaHoraSEPA(Fecha As DateTime) As String
                Return Fecha.Year.ToString & Fecha.Month.ToString.PadLeft(2, "0") & Fecha.Day.ToString.PadLeft(2, "0") & Fecha.Hour.ToString.PadLeft(2, "0") & Fecha.Minute.ToString.PadLeft(2, "0") & Fecha.Second.ToString.PadLeft(2, "0") & Fecha.Millisecond.ToString.PadLeft(5, "0")
            End Function


        End Class

    End Namespace
End Namespace
