unit CVBNorma19SEPA; interface uses Messages, SysUtils, Classes, Dialogs; type TSEPAPresentador = record Nombre : string; NIFCIF : string; Sufijo : string; end; TSEPAFichero = record Fecha : TDateTime; Identificador : string; end; TSEPAReceptor = record Oficina : string; Entidad : string; end; TSEPAAcreedor = record Nombre : string; Direccion1 : string; Direccion2 : string; Direccion3 : string; Pais : string; CuentaIBAN : string; Sufijo : string; NIFCIF : string; end; TSEPADeudor = record Nombre : string; Direccion1 : string; Direccion2 : string; Direccion3 : string; Pais : string; CuentaIBAN : string; CodigoBIC : string; end; TSEPAAdeudo = record Referencia : string; Importe : Currency; end; TCVBNorma19SEPA = class(TComponent) private pReg: array[0..602] of char; // 2 digitos más por el #13 #10 _LL_: integer; // Longitud Línea. Aquí almacenamos el valor 164 para usarlo // en el resto del componente. _INDICA_: string; _CERO_, _SPCE_: char; _MSK_EU_: string; _PAIS_DEFECTO_ : string; HayError: boolean; FDepura: boolean; NFic: file; FEnCasoError: TNotifyEvent; sReg: string; CRLF: string; sPrimerosDigitos: string; cSumaImportesTotalesAdeudos : Currency; // Suma de los importes (campo 8) en los registros 003 (adeudos) iNumeroRegistrosAdeudos: integer; // Número de registros individuales '003', adeudos iNumeroRegistrosAcreedor : integer; // Número de registros de un bloque de acreedor (002, 003 y 004) iNumeroRegistros: integer; // Nº de registros individuales (tipo '003') iTotalRegistros: integer; // Total de registros del fichero incluida el registro cabecera y el registro de totales generales procedure ComprobarDatos(sParte: string); protected procedure Error(iErr: integer); dynamic; public NrError: integer; FNomFic: string; // Nombre del archivo en disco Presentador : TSEPAPresentador; Fichero : TSEPAFichero; Receptor : TSEPAReceptor; Acreedor : TSEPAAcreedor; Deudor : TSEPADeudor; Adeudo : TSEPAAdeudo; FecAbono: TDateTime; FechaCobro : TDateTime; constructor Create(AOwner: TComponent); override; procedure Abrir; procedure GenerarCabeceraPresentador; procedure GenerarCabeceraAcreedor; procedure GenerarRegistroAdeudo; procedure GenerarTotalAcreedor; procedure Cerrar; published property NomFichero: string Read FNomFic Write FNomFic; property Depura: boolean Read FDepura Write FDepura default False; property EnCasoError: TNotifyEvent Read FEnCasoError Write FEnCasoError; { Published declarations } end; implementation uses Windows, uStringsUtils, CVBUtils; constructor TCVBNorma19SEPA.Create(AOwner: TComponent); begin inherited Create(AOwner); {Asignar la propiedades por defecto} _LL_ := high(pReg); _INDICA_ := '<--'; _CERO_ := '0'; _SPCE_ := ' '; _MSK_EU_ := '00000000.00'; _PAIS_DEFECTO_ := 'ES'; end; //******************************************************************************* procedure TCVBNorma19SEPA.Abrir; begin HayError := False; AssignFile(NFic, FNomFic); {$I+} rewrite(Nfic, _LL_); {$I-} if IOResult <> 0 then Error(0); iNumeroRegistros := 0; iTotalRegistros := 0; {fTotImpOrdEu := 0; iTotImpOrdPts := 0; iTotDomOrd := 0; iTotRegOrd := 0; fTotImpCinEu := 0; iTotImpCinPts := 0; iTotDomCin := 0; IniOrdenan; IniRegistro;} CRLF := #13 + #10; end; procedure TCVBNorma19SEPA.GenerarCabeceraPresentador; var auxDC : integer; auxIdentificador : string; begin HayError := False; sReg := ''; ComprobarDatos('01'); // Código de registro (2) sReg := '01'; // Versión del cuaderno (5) sReg := sReg + '19143'; // Número del dato (3) sReg := sReg + '001'; // Adeudo directo // Identificador del presentador (35) auxIdentificador := Presentador.NIFCIF + _PAIS_DEFECTO_ + '00'; auxDC := Modulo9710(auxIdentificador); sReg := sReg + _PAIS_DEFECTO_; sReg := sReg + Ajusta(IntToStr(auxDC), 'I', 2, _CERO_); sReg := sReg + Ajusta(Presentador.Sufijo, 'I', 3, _CERO_); sReg := sReg + Ajusta(Presentador.NIFCIF, 'D', 28, _SPCE_); // Nombre del presentador (70) sReg := sReg + Ajusta(Presentador.Nombre, 'D', 70, _SPCE_); // Fecha de creación del fichero (8) sReg := sReg + Ajusta(FormatDateTime('yyyymmdd', Fichero.Fecha), 'I', 8, _SPCE_); // Identificación del fichero (35) auxIdentificador := 'PRE' + FormatDateTime('yyyymmddhhnnsszzz', Now); auxIdentificador := auxIdentificador + Fichero.Identificador; auxIdentificador := UpperCase(ReplaceAccents(auxIdentificador)); auxIdentificador := StringReplace(auxIdentificador, ' ' , '', [rfReplaceAll]); sReg := sReg + Ajusta(auxIdentificador, 'D', 35, _SPCE_); // Entidad receptora (4) sReg := sReg + Ajusta(Receptor.Entidad, 'I', 4, _CERO_); // Oficina receptora (4) sReg := sReg + Ajusta(Receptor.Oficina, 'I', 4, _CERO_); // Libre (434) sReg := sReg + Ajusta('', 'D', 434, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); Inc(iTotalRegistros); end; procedure TCVBNorma19SEPA.GenerarRegistroAdeudo; var auxDC : integer; auxCadena : string; begin HayError := False; sReg := ''; ComprobarDatos('03'); // Código de registro (2) sReg := '03'; // Versión del cuaderno (5) sReg := sReg + '19143'; // Número de dato (3) sReg := sReg + '003'; // Referencia del adeudo (AT-10) (35) auxCadena := Adeudo.Referencia; auxCadena := auxCadena + FormatDateTime('yyyymmddhhnnsszzz', Now); sReg := sReg + Ajusta(auxCadena, 'D', 35, _SPCE_); // Referencia única del mandato (AT-01) (35) sReg := sReg + Ajusta(Adeudo.Referencia, 'D', 35, _SPCE_); // Tipo de adeudo (AT-21) (4) sReg := sReg + 'OOFF'; // Categoría del propósito (AT-59) (4) sReg := sReg + Ajusta('', 'D', 4, _SPCE_); // Importe del adeudo (AT-06) (11) auxCadena := FormatFloat(_MSK_EU_, Adeudo.Importe); auxCadena := StringReplace(auxCadena, DecimalSeparator, '', [rfReplaceAll]); sReg := sReg + Ajusta(auxCadena, 'I', 11, _CERO_); // Fecha de firma del mandato (AT-25) (8) sReg := sReg + Ajusta(FormatDateTime('yyyymmdd', Now), 'D', 8, _CERO_); // Entidad del deudor (AT-13) (11) sReg := sReg + Ajusta(Deudor.CodigoBIC, 'D', 11, _SPCE_); // Nombre del deudor (AT-14) (70) sReg := sReg + Ajusta(Deudor.Nombre, 'D', 70, _SPCE_); // Dirección del deudor D1 (AT-09) (50) sReg := sReg + Ajusta(Deudor.Direccion1, 'D', 50, _SPCE_); // Dirección del deudor D2 (AT-09) (50) sReg := sReg + Ajusta(Deudor.Direccion2, 'D', 50, _SPCE_); // Dirección del deudor D3 (AT-09) (40) sReg := sReg + Ajusta(Deudor.Direccion3, 'D', 40, _SPCE_); // País del deudor (AT-09) (2) sReg := sReg + _PAIS_DEFECTO_; // Tipo de identificación del deudor (1) sReg := sReg + ' '; // optativo // Identificación del deudor (código) (AT-27) (36) sReg := sReg + Ajusta('', 'D', 36, _SPCE_); // Identificación del deudor emisor código (otro) (AT-27) (35) sReg := sReg + Ajusta('', 'D', 35, _SPCE_); // Identificador de la cuenta del deudor (1) sReg := sReg + 'A'; // A -> IBAN // Cuenta del deudor (AT-07) (34) sReg := sReg + Ajusta(Deudor.CuentaIBAN, 'D', 34, _SPCE_); // Propósito del adeudo (AT-58) (4) sReg := sReg + Ajusta('', 'D', 4, _SPCE_); // Concepto (AT-22) (140) sReg := sReg + Ajusta('', 'D', 140, _SPCE_); // Libre (19) sReg := sReg + Ajusta('', 'D', 19, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); cSumaImportesTotalesAdeudos := cSumaImportesTotalesAdeudos + Adeudo.Importe; Inc(iNumeroRegistrosAcreedor); Inc(iNumeroRegistrosAdeudos); Inc(iTotalRegistros); Inc(iNumeroRegistros); end; procedure TCVBNorma19SEPA.GenerarTotalAcreedor; var auxDC : integer; auxIdentificador, auxCadena : string; begin HayError := False; sReg := ''; Inc(iNumeroRegistrosAcreedor); // Código de registro (2) sReg := '04'; // Identificador del acreedor (AT-02) (35) auxIdentificador := Acreedor.NIFCIF + _PAIS_DEFECTO_ + '00'; auxDC := Modulo9710(auxIdentificador); sReg := sReg + _PAIS_DEFECTO_; sReg := sReg + Ajusta(IntToStr(auxDC), 'I', 2, _CERO_); sReg := sReg + Ajusta(Acreedor.Sufijo, 'I', 3, _CERO_); sReg := sReg + Ajusta(Acreedor.NIFCIF, 'D', 28, _SPCE_); // Fecha de cobro (AT-11) (8) sReg := sReg + Ajusta(FormatDateTime('yyyymmdd', FechaCobro), 'I', 8, _SPCE_); // Total de importes (17) auxCadena := FormatFloat(_MSK_EU_, cSumaImportesTotalesAdeudos); auxCadena := StringReplace(auxCadena, DecimalSeparator, '', [rfReplaceAll]); sReg := sReg + Ajusta(auxCadena, 'I', 17, _CERO_); // Número de adeudos (8) sReg := sReg + Ajusta(IntToStr(iNumeroRegistrosAdeudos), 'I', 8, _CERO_); // Total de registros (10) sReg := sReg + Ajusta(IntToStr(iNumeroRegistrosAcreedor), 'I', 10, _CERO_); // Libre (520) sReg := sReg + Ajusta('', 'D', 520, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); Inc(iTotalRegistros); Inc(iNumeroRegistrosAcreedor); // Código de registro (2) sReg := '05'; // Identificador del acreedor (AT-02) (35) auxIdentificador := Acreedor.NIFCIF + _PAIS_DEFECTO_ + '00'; auxDC := Modulo9710(auxIdentificador); sReg := sReg + _PAIS_DEFECTO_; sReg := sReg + Ajusta(IntToStr(auxDC), 'I', 2, _CERO_); sReg := sReg + Ajusta(Acreedor.Sufijo, 'I', 3, _CERO_); sReg := sReg + Ajusta(Acreedor.NIFCIF, 'D', 28, _SPCE_); // Total de importes (17) auxCadena := FormatFloat(_MSK_EU_, cSumaImportesTotalesAdeudos); auxCadena := StringReplace(auxCadena, DecimalSeparator, '', [rfReplaceAll]); sReg := sReg + Ajusta(auxCadena, 'I', 17, _CERO_); // Número de adeudos (8) sReg := sReg + Ajusta(IntToStr(iNumeroRegistrosAdeudos), 'I', 8, _CERO_); // Total de registros (10) sReg := sReg + Ajusta(IntToStr(iNumeroRegistrosAcreedor), 'I', 10, _CERO_); // Libre (528) sReg := sReg + Ajusta('', 'D', 528, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); Inc(iTotalRegistros); end; procedure TCVBNorma19SEPA.GenerarCabeceraAcreedor; var auxDC : integer; auxIdentificador : string; begin HayError := False; sReg := ''; iNumeroRegistrosAdeudos := 0; iNumeroRegistrosAcreedor := 0; cSumaImportesTotalesAdeudos := 0; ComprobarDatos('02'); // Código de registro (2) sReg := '02'; // Versión del cuaderno (5) sReg := sReg + '19143'; // Número de dato (3) sReg := sReg + '002'; // Identificador del acreedor (AT-02) (35) auxIdentificador := Acreedor.NIFCIF + _PAIS_DEFECTO_ + '00'; auxDC := Modulo9710(auxIdentificador); sReg := sReg + _PAIS_DEFECTO_; sReg := sReg + Ajusta(IntToStr(auxDC), 'I', 2, _CERO_); sReg := sReg + Ajusta(Acreedor.Sufijo, 'I', 3, _CERO_); sReg := sReg + Ajusta(Acreedor.NIFCIF, 'D', 28, _SPCE_); // Fecha de cobro (AT-11) (8) sReg := sReg + Ajusta(FormatDateTime('yyyymmdd', FechaCobro), 'I', 8, _SPCE_); // Nombre del acreedor (AT-03) (70) sReg := sReg + Ajusta(Acreedor.Nombre, 'D', 70, _SPCE_); // Dirección del acreedor D1 (AT-05) (50) sReg := sReg + Ajusta(Acreedor.Direccion1, 'D', 50, _SPCE_); // Dirección del acreedor D2 (AT-05) (50) sReg := sReg + Ajusta(Acreedor.Direccion2, 'D', 50, _SPCE_); // Dirección del acreedor D3 (AT-05) (40) sReg := sReg + Ajusta(Acreedor.Direccion3, 'D', 40, _SPCE_); // País del acreedor (AT-05) (2) sReg := sReg + _PAIS_DEFECTO_; // Cuenta del acreedor (AT-04) (34) sReg := sReg + Ajusta(Acreedor.CuentaIBAN, 'D', 34, _SPCE_); // Libre (301) sReg := sReg + Ajusta('', 'D', 301, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); Inc(iNumeroRegistrosAcreedor); Inc(iTotalRegistros); end; procedure TCVBNorma19SEPA.ComprobarDatos(sParte: string); var bError: boolean; begin bError := False; if sParte = '01' then // cabecera / presentador begin if EsCadenaVacia(Presentador.NIFCIF) then begin Presentador.NIFCIF := _INDICA_; bError := True; end else Presentador.NIFCIF := UpperCase(Presentador.NIFCIF); if EsCadenaVacia(Presentador.Sufijo) then begin Presentador.Sufijo := _INDICA_; bError := True; end; if EsCadenaVacia(Presentador.Nombre) then begin Presentador.Nombre := _INDICA_; bError := True; end else Presentador.Nombre := UpperCase(ReplaceAccents(Presentador.Nombre)); if EsCadenaVacia(Fichero.Identificador) then begin Fichero.Identificador := _INDICA_; bError := True; end; if EsCadenaVacia(Receptor.Entidad) then begin Receptor.Entidad := _INDICA_; bError := True; end; if EsCadenaVacia(Receptor.Oficina) then begin Receptor.Oficina := _INDICA_; bError := True; end; if bError then ShowMessage('Faltan datos al procesar el registro 01: ' + CRLF + CRLF + 'NIF/CIF del presentador: ' + Presentador.NIFCIF + CRLF + 'Sufijo del presentador: ' + Presentador.Sufijo + CRLF + 'Nombre del presentador: ' + Presentador.Nombre + CRLF + 'Identificador del fichero: ' + Fichero.Identificador + CRLF + 'Cód. entidad del receptor: ' + Receptor.Entidad + CRLF + 'Cód. oficina del receptor: ' + Receptor.Oficina + CRLF ); end; if sParte = '02' then // acreedor begin if EsCadenaVacia(Acreedor.NIFCIF) then begin Acreedor.NIFCIF := _INDICA_; bError := True; end else Acreedor.NIFCIF := UpperCase(Acreedor.NIFCIF); if EsCadenaVacia(Acreedor.Nombre) then begin Acreedor.Nombre := _INDICA_; bError := True; end else Acreedor.Nombre := UpperCase(ReplaceAccents(Acreedor.Nombre)); if EsCadenaVacia(Acreedor.Direccion1) then begin Acreedor.Direccion1 := _INDICA_; bError := True; end else Acreedor.Direccion1 := UpperCase(ReplaceAccents(Acreedor.Direccion1)); Acreedor.Direccion2 := UpperCase(ReplaceAccents(Acreedor.Direccion2)); Acreedor.Direccion3 := UpperCase(ReplaceAccents(Acreedor.Direccion3)); Acreedor.Pais := UpperCase(ReplaceAccents(Acreedor.Pais)); if EsCadenaVacia(Acreedor.CuentaIBAN) then begin Acreedor.CuentaIBAN := _INDICA_; bError := True; end; if EsCadenaVacia(Acreedor.Sufijo) then begin Acreedor.Sufijo := _INDICA_; bError := True; end; if bError then ShowMessage('Faltan datos al procesar el registro 02: ' + CRLF + CRLF + 'NIF/CIF del acreedor: ' + Acreedor.NIFCIF + CRLF + 'Sufijo del acreedor: ' + Acreedor.Sufijo + CRLF + 'Nombre del acreedor: ' + Acreedor.Nombre + CRLF + 'Cuenta IBAN del acreedor: ' + Acreedor.CuentaIBAN + CRLF + 'Dirección 1 del acreedor: ' + Acreedor.Direccion1 + CRLF ); end; if sParte = '03' then // deudor begin // Quitar espacios y caracteres no estándar Adeudo.Referencia := StringReplace(UpperCase(ReplaceAccents(Adeudo.Referencia)), ' ', '', [rfReplaceAll]); if EsCadenaVacia(Deudor.Nombre) then begin Deudor.Nombre := _INDICA_; bError := True; end else Deudor.Nombre := UpperCase(ReplaceAccents(Deudor.Nombre)); if EsCadenaVacia(Deudor.Direccion1) then begin Deudor.Direccion1 := _INDICA_; bError := True; end else Deudor.Direccion1 := UpperCase(ReplaceAccents(Deudor.Direccion1)); Deudor.Direccion2 := UpperCase(ReplaceAccents(Deudor.Direccion2)); Deudor.Direccion3 := UpperCase(ReplaceAccents(Deudor.Direccion3)); Deudor.Pais := UpperCase(ReplaceAccents(Deudor.Pais)); if EsCadenaVacia(Deudor.CuentaIBAN) then begin Deudor.CuentaIBAN := _INDICA_; bError := True; end; // No obligar a tener código BIC/SWIFT {if EsCadenaVacia(Deudor.CodigoBIC) then begin Deudor.CodigoBIC := _INDICA_; bError := True; end;} if bError then ShowMessage('Faltan datos al procesar el registro 03: ' + CRLF + CRLF + 'Nombre del deudor: ' + Deudor.Nombre + CRLF + 'Dirección 1 del deudor: ' + Deudor.Direccion1 + CRLF + 'Cuenta IBAN del deudor: ' + Deudor.CuentaIBAN + CRLF + 'Código BIC del deudor: ' + Deudor.CodigoBIC ); end; end; procedure TCVBNorma19SEPA.Cerrar; var auxCadena : string; begin HayError := False; sReg := ''; Inc(iTotalRegistros); // Código de registro sReg := '99'; // Total de importes general (17) auxCadena := FormatFloat(_MSK_EU_, cSumaImportesTotalesAdeudos); auxCadena := StringReplace(auxCadena, DecimalSeparator, '', [rfReplaceAll]); sReg := sReg + Ajusta(auxCadena, 'I', 17, _CERO_); // Número de registros (8) sReg := sReg + Ajusta(IntToStr(iNumeroRegistros), 'I', 8, _CERO_); // Total de registros (10) sReg := sReg + Ajusta(IntToStr(iTotalRegistros), 'I', 10, _CERO_); // Libre (563) sReg := sReg + Ajusta('', 'D', 563, _SPCE_); // Fin sReg := sReg + CRLF; StrPCopy(@pReg, sReg); BlockWrite(NFic, pReg, 1); if not (length(sReg) = _LL_) then Error(_LL_); CloseFile(NFic); end; procedure TCVBNorma19SEPA.Error(iErr: integer); begin NrError := iErr; HayError := True; if Assigned(FEnCasoError) then FEnCasoError(Self) else CloseFile(NFic); if NrError = _LL_ then raise Exception.Create('Error en la longitud de la línea') else raise Exception.Create('Error en la generación del fichero'); end; end.