From a80cf72851c1a0794489bfa551e0448fda43e3a7 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 25 Jan 2016 11:52:35 +0000 Subject: [PATCH] =?UTF-8?q?Adaptaci=C3=B3n=20a=20normativa=20SEPA=20XML=20?= =?UTF-8?q?-=20Terminado=20pero=20sin=20probar=20con=20banco.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://192.168.0.254/svn/Proyectos.LuisLeon_FactuGES2/trunk@244 b2cfbe5a-eba1-4a0c-8b32-7feea0a119f2 --- Source/Base/Utiles/uDisplayUtils.pas | 67 ++ Source/Cliente/FactuGES.identcache | Bin 622 -> 622 bytes Source/Cliente/FactuGES.res | Bin 171984 -> 172184 bytes .../BancaElectronica_controller.dpk | Bin 1269 -> 1602 bytes .../BancaElectronica_controller.dproj | 5 + .../uIEditorExportacionNorma19SEPAXML.pas | 32 + .../uBancaElectronicaController.pas | 197 +++- .../Utiles/CVBNorma19SEPAXML.pas | 428 +++++++++ .../Banca electronica/Utiles/CVBUtils.pas | 2 - .../Utiles/SEPAUnit/SEPACommon.dcu | Bin 0 -> 20805 bytes .../Utiles/SEPAUnit/SEPACommon.pas | 587 ++++++++++++ .../Utiles/SEPAUnit/SEPACreditTransfer.dcu | Bin 0 -> 21535 bytes .../Utiles/SEPAUnit/SEPACreditTransfer.pas | 565 ++++++++++++ .../Utiles/SEPAUnit/SEPADirectDebit.dcu | Bin 0 -> 33353 bytes .../Utiles/SEPAUnit/SEPADirectDebit.pas | 861 ++++++++++++++++++ .../Banca electronica/Utiles/SEPAUnit/gpl.txt | 357 ++++++++ .../Utiles/SEPAUnit/license.txt | 3 + .../Views/BancaElectronica_view.dpk | 3 +- .../Views/BancaElectronica_view.dproj | 49 +- .../Views/uBancaElectronicaViewRegister.pas | 8 +- .../uEditorExportacionNorma19SEPAXML.dfm | 234 +++++ .../uEditorExportacionNorma19SEPAXML.pas | 166 ++++ .../Views/uEditorRemesaCliente.dfm | 137 +-- .../Views/uEditorRemesaCliente.pas | 29 +- Source/Servidor/FactuGES_Server.RES | Bin 23212 -> 23200 bytes Source/Servidor/FactuGES_Server.rc | 2 +- 26 files changed, 3641 insertions(+), 91 deletions(-) create mode 100644 Source/Base/Utiles/uDisplayUtils.pas create mode 100644 Source/Modulos/Banca electronica/Controller/View/uIEditorExportacionNorma19SEPAXML.pas create mode 100644 Source/Modulos/Banca electronica/Utiles/CVBNorma19SEPAXML.pas create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACommon.dcu create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACommon.pas create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACreditTransfer.dcu create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACreditTransfer.pas create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPADirectDebit.dcu create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPADirectDebit.pas create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/gpl.txt create mode 100644 Source/Modulos/Banca electronica/Utiles/SEPAUnit/license.txt create mode 100644 Source/Modulos/Banca electronica/Views/uEditorExportacionNorma19SEPAXML.dfm create mode 100644 Source/Modulos/Banca electronica/Views/uEditorExportacionNorma19SEPAXML.pas diff --git a/Source/Base/Utiles/uDisplayUtils.pas b/Source/Base/Utiles/uDisplayUtils.pas new file mode 100644 index 0000000..4228e49 --- /dev/null +++ b/Source/Base/Utiles/uDisplayUtils.pas @@ -0,0 +1,67 @@ +unit uDisplayUtils; + +interface + + +uses + Windows, SysUtils, Variants, Classes, Graphics, Controls, Forms, + uGUIBase, uCustomEditor; + +procedure ScaleFormFont(AForm : TForm); + +implementation + +uses + TypInfo; + +procedure SetFontProperties(Control: TControl; Name: TFontName; Size: Integer; Styles: TFontStyles); +// Set font properties +var + Index: Integer; + Font: TFont; + AnObject: TObject; + ChildControl: TControl; +begin + // Set font properties + try + AnObject := GetObjectProp(Control, 'Font', nil); + if AnObject is TFont then + begin + // Set properties + Font := TFont(AnObject); + Font.Name := Name; + Font.Size := Size; + Font.Style := Styles; + end; + except + // ignorar las excepciones EPropertyError por no encontrar la propiedad + + end; + + // Set child font properties + if Control is TWinControl then + begin + // Set + for Index := 0 to TWinControl(Control).ControlCount - 1 do + begin + // Child control + ChildControl := TWinControl(Control).Controls[Index]; + + // Set font properties + try + SetFontProperties(ChildControl, Name, Size, Styles); + except + // ignorar las excepciones EPropertyError por no encontrar la propiedad + end; + end; + end; +end; + +procedure ScaleFormFont(AForm : TForm); +begin + AForm.ScaleBy(Screen.PixelsPerInch, 96); + SetFontProperties(AForm, Screen.IconFont.Name, Screen.IconFont.Size, Screen.IconFont.Style); +end; + +end. + diff --git a/Source/Cliente/FactuGES.identcache b/Source/Cliente/FactuGES.identcache index fd9914e9899b53e3142f7a09448eb1229e76e545..6193afd4a36bd3180f7cb14b62111191c29e3050 100644 GIT binary patch delta 34 qcmaFI@{VPK!(>H9LDq&v(5NUhPVh9=B^28TZr}`#-~#L0 z_iRiu^JdDI?SXX(Ri=hAo08x}?TI_%t?38X;LQ(ItbTWY1CI3KHR6UTQ z^-)eBgG!YE3oUqkojUiT?m)Ni_FgILv3&h=(HM~oh3x|{j0ZVK(!Nr6W6Grxr y>l5K%M4r!gg(+>4FxcKt!=quWoSYO-K6yG+=^|b(uaAhWeZ88~R?Dg5McQBDRyGX) delta 101 zcmbPnkn6&Ju7(!IEldaIDt%yNU{GLSVEF%E0EmGcATVIy;sG;�SRdkLEIYh_Em~ oaUM>ZNVAlXgm&~HnW}gkC%%90F|syH2?qr delta 20 bcmX@a^ObYMOBNn$UM^m))VvfuUM>azNGJtc diff --git a/Source/Modulos/Banca electronica/Controller/BancaElectronica_controller.dproj b/Source/Modulos/Banca electronica/Controller/BancaElectronica_controller.dproj index d19a7ce..ee78423 100644 --- a/Source/Modulos/Banca electronica/Controller/BancaElectronica_controller.dproj +++ b/Source/Modulos/Banca electronica/Controller/BancaElectronica_controller.dproj @@ -54,6 +54,7 @@ + @@ -61,10 +62,14 @@ + + + + diff --git a/Source/Modulos/Banca electronica/Controller/View/uIEditorExportacionNorma19SEPAXML.pas b/Source/Modulos/Banca electronica/Controller/View/uIEditorExportacionNorma19SEPAXML.pas new file mode 100644 index 0000000..fb5d799 --- /dev/null +++ b/Source/Modulos/Banca electronica/Controller/View/uIEditorExportacionNorma19SEPAXML.pas @@ -0,0 +1,32 @@ +unit uIEditorExportacionNorma19SEPAXML; + +interface + +type + IEditorExportacionNorma19SEPAXML = interface + ['{AE5B7884-D53B-4384-821E-72A968A9CC8C}'] + + procedure SetCodigoEntidad(const AValue: String); + function GetCodigoEntidad : String; + property CodigoEntidad : String read GetCodigoEntidad write SetCodigoEntidad; + + procedure SetCodigoAgencia(const AValue: String); + function GetCodigoAgencia : String; + property CodigoAgencia : String read GetCodigoAgencia write SetCodigoAgencia; + + procedure SetFechaCargo(const AValue: TDateTime); + function GetFechaCargo : TDateTime; + property FechaCargo : TDateTime read GetFechaCargo write SetFechaCargo; + + procedure SetFichero(const AValue: String); + function GetFichero : String; + property Fichero : String read GetFichero write SetFichero; + + function ShowModal : Integer; + procedure Release; + end; + + +implementation + +end. diff --git a/Source/Modulos/Banca electronica/Controller/uBancaElectronicaController.pas b/Source/Modulos/Banca electronica/Controller/uBancaElectronicaController.pas index 731d077..799b476 100644 --- a/Source/Modulos/Banca electronica/Controller/uBancaElectronicaController.pas +++ b/Source/Modulos/Banca electronica/Controller/uBancaElectronicaController.pas @@ -34,6 +34,7 @@ type ['{8C646A34-AFDF-4F09-A8BA-D6D40B5A91B8}'] procedure GenerarFicheroNorma19 (const IDRemesa : Integer); procedure GenerarFicheroNorma19SEPA (const IDRemesa : Integer); + procedure GenerarFicheroNorma19SEPAXML (const IDRemesa : Integer); procedure GenerarFicheroNorma32 (const IDRemesa : Integer); end; @@ -43,6 +44,8 @@ type var AFechaCargo : TDateTime; var AFileName : String): Boolean; function VerEditorNorma19SEPA(var Entidad : String; var Oficina : String; var AFechaCargo : TDateTime; var AFileName : String): Boolean; + function VerEditorNorma19SEPAXML(var Entidad : String; var Oficina : String; + var AFechaCargo : TDateTime; var AFileName : String): Boolean; function VerEditorNorma32(var Identificador : String; var ACodigoINE : String; var Entidad : String; var Oficina : String; var AFileName : String): Boolean; @@ -50,7 +53,8 @@ type function ValidarEmpresaParaSEPA(AEmpresa : IBizEmpresa) : Boolean; public procedure GenerarFicheroNorma19 (const IDRemesa : Integer); - procedure GenerarFicheroNorma19SEPA (const IDRemesa : Integer); + procedure GenerarFicheroNorma19SEPA (const IDRemesa : Integer); + procedure GenerarFicheroNorma19SEPAXML (const IDRemesa : Integer); procedure GenerarFicheroNorma32 (const IDRemesa : Integer); end; @@ -67,7 +71,9 @@ uses schRecibosClienteClient_Intf, Dialogs, uIEditorExportacionNorma19, uIEditorExportacionNorma32, uBizRecibosCliente, schContactosClient_Intf, schEmpresasClient_Intf, - uIEditorExportacionNorma19SEPA, CVBNorma19SEPA; + uIEditorExportacionNorma19SEPA, CVBNorma19SEPA, + uIEditorExportacionNorma19SEPAXML, + CVBNorma19SEPAXML; { TBancaElectronicaController } @@ -350,6 +356,156 @@ begin end; end; +procedure TBancaElectronicaController.GenerarFicheroNorma19SEPAXML( + const IDRemesa: Integer); +var + ARemesasController : IRemesasClienteController; + AEmpresasController : IEmpresasController; + AClientesController : IClientesController; + + ARemesa : IBizRemesaCliente; + AEmpresa : IBizEmpresa; + ACliente : IBizCliente; + + I: integer; + AEntidad : String; + AOficina : String; + + ANorma19 : TCVBNorma19SEPAXML; +begin + ARemesasController := TRemesasClienteController.Create; + AEmpresasController := TEmpresasController.Create; + AClientesController := TClientesController.Create; + + try + ARemesa := ARemesasController.Buscar(IDRemesa); + ARemesa.DataTable.Active := True; + ARemesasController.RecuperarRecibos(ARemesa); + + if ARemesa.ID <> IDRemesa then + raise Exception.CreateFmt('No existe la remesa con ID %d', [IDRemesa]); + + AEmpresa := AEmpresasController.Buscar(ARemesa.ID_EMPRESA); + AEmpresa.DataTable.Active := True; + + if AEmpresa.ID <> ARemesa.ID_EMPRESA then + raise Exception.CreateFmt('No existe la empresa con ID %d', [ARemesa.ID_EMPRESA]); + + ANorma19 := TCVBNorma19SEPAXML.Create(NIL); + + ANorma19.FNomFic := 'REM' + ARemesa.REFERENCIA + '.XML'; + ANorma19.Fichero.Fecha := Date; + ANorma19.Fichero.Identificador := AEmpresa.NIF_CIF + ARemesa.REFERENCIA; + ANorma19.FechaCobro := Date; + + // Buscar los datos bancarios + with AEmpresa.DatosBancarios do + begin + First; + if Locate('ID', ARemesa.ID_DATOS_BANCO, []) then + begin + AEntidad := ENTIDAD; + AOficina := SUCURSAL; + end; + end; + + ValidarEmpresaParaSEPA(AEmpresa); + + ValidarRemesaParaSEPA(ARemesa); + + if not VerEditorNorma19SEPAXML(AEntidad, AOficina, ANorma19.FechaCobro, ANorma19.FNomFic) then + Exit; + + ShowHourglassCursor; + + ANorma19.Receptor.Entidad := AEntidad; + ANorma19.Receptor.Oficina := AOficina; + + with ANorma19 do + begin + Depura := True; + + Abrir; + + // PRESENTADOR + if AEmpresa.DatosBancarios.NIF_CIF_PRESENTADORIsNull then + Presentador.NIFCIF := AEmpresa.NIF_CIF + else + Presentador.NIFCIF := AEmpresa.DatosBancarios.NIF_CIF_PRESENTADOR; + + if AEmpresa.DatosBancarios.SUFIJO_PRESENTADORIsNull then + Presentador.Sufijo := AEmpresa.DatosBancarios.SUFIJO_ACREEDOR + else + Presentador.Sufijo := AEmpresa.DatosBancarios.SUFIJO_PRESENTADOR; + + if AEmpresa.DatosBancarios.NOMBRE_PRESENTADORIsNull then + Presentador.Nombre := AEmpresa.NOMBRE + else + Presentador.Nombre := AEmpresa.DatosBancarios.NOMBRE_PRESENTADOR; + + GenerarCabeceraPresentador; + + + // ACREEDOR + Acreedor.NIFCIF := AEmpresa.NIF_CIF; + Acreedor.Nombre := AEmpresa.NOMBRE; + Acreedor.Direccion1 := AEmpresa.CALLE; + + if not AEmpresa.CODIGO_POSTALIsNull then + Acreedor.Direccion2 := AEmpresa.CODIGO_POSTAL + ' '; + + Acreedor.Direccion2 := Acreedor.Direccion2 + AEmpresa.POBLACION; + Acreedor.Direccion3 := AEmpresa.PROVINCIA; + Acreedor.Pais := 'ES'; + Acreedor.Sufijo := AEmpresa.DatosBancarios.SUFIJO_ACREEDOR; + Acreedor.CuentaIBAN := AEmpresa.DatosBancarios.IBAN; + + GenerarCabeceraAcreedor; + + ARemesa.Recibos.DataTable.First; + for I := 0 to (ARemesa.Recibos.DataTable.RecordCount - 1) do + begin + //ACliente := (AClientesController.Buscar(ARemesa.Recibos.ID_CLIENTE) as IBizCliente); + //ACliente.Open; + + // DEUDOR + Deudor.Nombre := ARemesa.Recibos.NOMBRE_CLIENTE; + Deudor.Direccion1 := ARemesa.Recibos.CALLE_CLIENTE; + + if not ARemesa.Recibos.CODIGO_POSTAL_CLIENTEIsNull then + Deudor.Direccion2 := ARemesa.Recibos.CODIGO_POSTAL_CLIENTE + ' '; + + Deudor.Direccion2 := Deudor.Direccion2 + ARemesa.Recibos.POBLACION_CLIENTE; + Deudor.Direccion3 := ARemesa.Recibos.PROVINCIA_CLIENTE; + Deudor.Pais := 'ES'; + Deudor.CuentaIBAN := ARemesa.Recibos.IBAN_CLIENTE; + Deudor.CodigoBIC := ARemesa.Recibos.SWIFT_CLIENTE; + + Adeudo.Referencia := ARemesa.Recibos.REFERENCIA; + Adeudo.Importe := ARemesa.Recibos.IMPORTE_TOTAL; + + GenerarRegistroAdeudo; + + ARemesa.Recibos.DataTable.Next; + end; + + GenerarTotalAcreedor; + Cerrar; + + ShowMessage('Se ha generado el fichero'); + end; + finally + HideHourglassCursor; + ARemesasController := NIL; + AEmpresasController := NIL; + AClientesController := NIL; + + AEmpresa := NIL; + + FreeAndNil(ANorma19); + end; +end; + procedure TBancaElectronicaController.GenerarFicheroNorma32( const IDRemesa: Integer); var @@ -638,6 +794,43 @@ begin end; +function TBancaElectronicaController.VerEditorNorma19SEPAXML(var Entidad, + Oficina: String; var AFechaCargo: TDateTime; var AFileName: String): Boolean; +var + AEditor : IEditorExportacionNorma19SEPAXML; +begin + Result := False; + AEditor := NIL; + ShowHourglassCursor; + try + CreateEditor('EditorExportacionNorma19SEPAXML', IEditorExportacionNorma19SEPAXML, AEditor); + with AEditor do + begin + CodigoEntidad := Entidad; + CodigoAgencia := Oficina; + FechaCargo := AFechaCargo; + Fichero := AFileName; + end; + finally + HideHourglassCursor; + end; + + if Assigned(AEditor) then + try + if (AEditor.ShowModal = mrOk) then + begin + Entidad := AEditor.CodigoEntidad; + Oficina := AEditor.CodigoAgencia; + AFechaCargo := AEditor.FechaCargo; + AFileName := AEditor.Fichero; + Result := True; + end; + AEditor.Release; + finally + AEditor := NIL; + end; +end; + function TBancaElectronicaController.VerEditorNorma32(var Identificador, ACodigoINE: String; var Entidad, Oficina: String; var AFileName: String): Boolean; diff --git a/Source/Modulos/Banca electronica/Utiles/CVBNorma19SEPAXML.pas b/Source/Modulos/Banca electronica/Utiles/CVBNorma19SEPAXML.pas new file mode 100644 index 0000000..ba1d172 --- /dev/null +++ b/Source/Modulos/Banca electronica/Utiles/CVBNorma19SEPAXML.pas @@ -0,0 +1,428 @@ +unit CVBNorma19SEPAXML; + +interface + +uses + Messages, SysUtils, Classes, Dialogs, SEPACommon, SEPADirectDebit; + +type + TSEPAXMLPresentador = record + Nombre : string; + NIFCIF : string; + Sufijo : string; + end; + + TSEPAXMLFichero = record + Fecha : TDateTime; + Identificador : string; + end; + + TSEPAXMLReceptor = record + Oficina : string; + Entidad : string; + end; + + TSEPAXMLAcreedor = record + Nombre : string; + Direccion1 : string; + Direccion2 : string; + Direccion3 : string; + Pais : string; + CuentaIBAN : string; + Sufijo : string; + NIFCIF : string; + end; + + TSEPAXMLDeudor = record + Nombre : string; + Direccion1 : string; + Direccion2 : string; + Direccion3 : string; + Pais : string; + CuentaIBAN : string; + CodigoBIC : string; + end; + + TSEPAXMLAdeudo = record + Referencia : string; + Importe : Currency; + end; + + + + TCVBNorma19SEPAXML = 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; + + + FEnCasoError: TNotifyEvent; + CRLF: 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 + + + FDDInit: TDirectDebitInitiation; + FDDPayInfo: TDirectDebitPaymentInformation; + FDDTransInfo: TDirectDebitTransactionInformation; + + procedure ComprobarDatos(sParte: string); + protected + procedure Error(iErr: integer); dynamic; + public + NrError: integer; + FNomFic: string; // Nombre del archivo en disco + + Presentador : TSEPAXMLPresentador; + Fichero : TSEPAXMLFichero; + Receptor : TSEPAXMLReceptor; + Acreedor : TSEPAXMLAcreedor; + Deudor : TSEPAXMLDeudor; + Adeudo : TSEPAXMLAdeudo; + + FecAbono: TDateTime; + + FechaCobro : TDateTime; + + constructor Create(AOwner: TComponent); override; + + procedure Abrir; + procedure GenerarCabeceraPresentador; + procedure GenerarCabeceraAcreedor; + procedure GenerarRegistroAdeudo; + procedure GenerarTotalAcreedor; + procedure Cerrar; + destructor Destroy; override; + 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 TCVBNorma19SEPAXML.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'; + + FDDInit := TDirectDebitInitiation.Create; + FDDInit.Schema := SCHEMA_PAIN_008_002_02; +end; + +destructor TCVBNorma19SEPAXML.Destroy; +begin +// FreeAndNil(FDDTransInfo); +// FreeAndNil(FDDPayInfo); + FreeAndNil(FDDInit); + inherited; +end; + +//******************************************************************************* + +procedure TCVBNorma19SEPAXML.Abrir; +begin + HayError := False; + + //AssignFile(NFic, FNomFic); +{$I+} + ///rewrite(Nfic, _LL_); +{$I-} +{ if IOResult <> 0 then + Error(0); + + iNumeroRegistros := 0; + iTotalRegistros := 0; + + CRLF := #13 + #10;} + +end; + + +procedure TCVBNorma19SEPAXML.GenerarCabeceraPresentador; +begin + HayError := False; + FDDInit.GrpHdrInitgPtyName := Presentador.Nombre; +end; + +procedure TCVBNorma19SEPAXML.GenerarRegistroAdeudo; +var + auxDC : integer; + auxCadena : string; +begin + HayError := False; + + auxCadena := Adeudo.Referencia; + auxCadena := auxCadena + FormatDateTime('yyyymmddhhnnsszzz', Now); + +// direct debit transaction (including mandate details) + FDDTransInfo := TDirectDebitTransactionInformation.Create; + FDDTransInfo.PmtIdEndToEndId := auxCadena; + FDDTransInfo.InstdAmt := Adeudo.Importe; + FDDTransInfo.DbtrNm := Deudor.Nombre; + FDDTransInfo.DbtrAcct.IBAN := Deudor.CuentaIBAN; + FDDTransInfo.DbtrAgt.BIC := Deudor.CodigoBIC; + FDDTransInfo.DbtrAgt.OthrID := ''; + FDDTransInfo.RmtInfUstrd := ''; + FDDTransInfo.DrctDbtTxMndtRltdInf.MndtId := Adeudo.Referencia; + FDDTransInfo.DrctDbtTxMndtRltdInf.DtOfSgntr := Now; + {FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInd := DD_MandateAmendmentInformationDetails_CheckBox.Checked; + FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlMndtId := DD_OriginalMandateId_Edit.Text; + FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlCdtrSchmeIdNm := DD_OriginalCreditorName_Edit.Text; + FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlCdtrSchmeIdIdPrvtIdOthrId := DD_OriginalCreditorIdentifier_Edit.Text; + FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlDbtrAcct.IBAN := DD_OriginalDebtorAccountIBAN_Edit.Text; + FDDTransInfo.DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlDbtrAgtFinInstIdOthrId := IfThen(DD_OriginalDebtorFinInstSMNDA_CheckBox.Checked, ORGNL_DBTR_AGT_SMNDA, '');} + FDDPayInfo.AppendDrctDbtTxInfEntry(FDDTransInfo); + +end; + +procedure TCVBNorma19SEPAXML.GenerarTotalAcreedor; +begin +end; + +procedure TCVBNorma19SEPAXML.GenerarCabeceraAcreedor; +begin + HayError := False; + + FDDPayInfo := TDirectDebitPaymentInformation.Create; + FDDPayInfo.PmtTpInfLclInstrmCd := LCL_INSTRM_CD_CORE; + FDDPayInfo.PmtTpInfSeqTp := SEQ_TP_OOFF; + FDDPayInfo.ReqdColltnDt := FechaCobro; + FDDPayInfo.CdtrNm := Acreedor.Nombre; + FDDPayInfo.CdtrAcct.IBAN := Acreedor.CuentaIBAN; + FDDPayInfo.CdtrAgt.BIC := ''; + FDDPayInfo.CdtrAgt.OthrID := FIN_INSTN_NOTPROVIDED; + FDDPayInfo.CdtrSchmeIdIdPrvtIdOthrId := Acreedor.CuentaIBAN; + FDDInit.AppendPmtInfEntry(FDDPayInfo); +end; + + + +procedure TCVBNorma19SEPAXML.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 TCVBNorma19SEPAXML.Cerrar; +var + messages : TStringList; +begin + + messages := FDDInit.Validate; + {if ((messages.Count = 0) or (MessageDlg(messages.Text, mtError, [mbOk, mbIgnore], 0) = mrIgnore)) and + SaveDialog.Execute then} + FDDInit.SaveToDisk(FNomFic); +end; + + +procedure TCVBNorma19SEPAXML.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. diff --git a/Source/Modulos/Banca electronica/Utiles/CVBUtils.pas b/Source/Modulos/Banca electronica/Utiles/CVBUtils.pas index 23ca799..a8b406e 100644 --- a/Source/Modulos/Banca electronica/Utiles/CVBUtils.pas +++ b/Source/Modulos/Banca electronica/Utiles/CVBUtils.pas @@ -64,8 +64,6 @@ end; function Trim(const cString: string): string; -var - I: integer; begin Result := TrimLeft(TrimRight(cString)); end; diff --git a/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACommon.dcu b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACommon.dcu new file mode 100644 index 0000000000000000000000000000000000000000..9985bb2d887086461f6e18c91111269780b8576c GIT binary patch literal 20805 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 2009: Unicode strings + // c) for Lazarus: no encoding specified, ANSI is assumed + + TFinancialInstitution = class + private + fBIC: String; // financial institution identification: BIC (8 or 11 characters) + fOthrID: String; // other identification: used for IBAN-only ("NOTPROVIDED") + + procedure SetBIC(const str: String); + public + property BIC: String read fBIC write SetBIC; + property OthrID: String read fOthrID write fOthrID; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TAccountIdentification = class + private + fIBAN: String; // account identification: IBAN + + procedure SetIBAN(const str: String); + public + property IBAN: String read fIBAN write SetIBAN; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + +function SEPAGenerateUUID: String; + +function SEPACleanIBANorBICorCI(s: String): String; +function SEPAModulo97(const str: String): Integer; +function SEPACheckIBAN(const iban: String): Boolean; +function SEPACheckBIC(const bic: String): Boolean; +function SEPACheckCI(const ci: String): Boolean; +function SEPAIsGermanIBAN(const iban: String): Boolean; + +function SEPACleanString(const s: String; const maxlen: Integer = -1): String; +function SEPACheckString(const s: String; const maxlen: Integer = -1): Boolean; + +function SEPACheckRounded(const d: Currency): Boolean; +function SEPAFormatAmount(const d: Currency; const digits: Integer = 2): String; +function SEPAFormatBoolean(const b: Boolean): String; +function SEPAFormatDate(const d: TDateTime): String; +function SEPAFormatDateTime(const d: TDateTime): String; + +procedure SEPAWriteLine(const stream: TStream; const line: String); + +var + SEPASupportSpecialChars: Boolean = false; // support for German special characters, + // only allowed in "pain.001.003.03" and + // in "pain.008.003.02" + +implementation + +// private methods and code for better compiler compatibility + +{$IFNDEF FPC} +{$IF CompilerVersion >= 15} +{$IF CompilerVersion <= 21} // Delphi 7 to 2010: +uses // include unit Windows for the constant + Windows; // LOCALE_SYSTEM_DEFAULT +{$IFEND} +{$IFEND} +{$ENDIF} + +{$IFDEF FPC} +type UTF8String = String; // just use the usual strings in Lazarus +{$ELSE} +{$IF CompilerVersion < 11} // also use the usual strings in Delphi < 2007 +type UTF8String = String; // (same definition as in Delphi 2007) +{$IFEND} +{$ENDIF} + +function StringToUTF8(const str: String): UTF8String; +begin + // note: just use conversion from Unicode to UTF-8 (in Unicode-based + // Delphi 2009 and higher), or conversion from ANSI to UTF-8 (for older + // Delphi versions and Lazarus). + Result := {$IFDEF Unicode}UTF8Encode{$ELSE}AnsiToUtf8{$ENDIF}(str); +end; + +{$IFDEF FPC} // Lazarus supports TFormatSettings and has +{$DEFINE FormatSettings} // a method "DefaultFormatSettings" +{$ELSE} +{$IF CompilerVersion >= 15} // Delphi 7 and higher supports TFormatSettings, +{$DEFINE FormatSettings} // but DefaultFormatSettings is not known +function DefaultFormatSettings: TFormatSettings; +begin +{$IF CompilerVersion >= 22} // Delphi XE and later + Result := TFormatSettings.Create; +{$ELSE} // Delphi 2010 and before + GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, Result); +{$IFEND} +end; +{$IFEND} +{$ENDIF} + +{$IFDEF FormatSettings} // format settings variable with correct +var // decimal separator, initialized in unit + SEPAFormatSettings: TFormatSettings; // "initialization" block below +{$ENDIF} + +function CharIsInInterval(const c: Char; const i1: Char; const i2: Char): Boolean; +begin + Result := ((Ord(c) >= Ord(i1)) and (Ord(c) <= Ord(i2))); +end; + +function CharIsSEPAWhitelisted(const c: Char): Boolean; +begin + // note: we do not use "c in [...]" syntax because that's only correct + // for strings with single-byte characters + Result := CharIsInInterval(c, 'A', 'Z') or + CharIsInInterval(c, 'a', 'z') or + CharIsInInterval(c, '0', '9') or + (c = '''') or (c = ':') or (c = '?') or + (c = ',') or (c = '-') or (c = ' ') or + (c = '(') or (c = '+') or (c = '.') or + (c = ')') or (c = '/'); +end; + +function CharIsGermanSpecialChar(const c: Char): Boolean; +begin + Result := (c = 'Ä') or (c = 'Ö') or (c = 'Ü') or + (c = 'ä') or (c = 'ö') or (c = 'ü') or + (c = 'ß') or (c = '&') or (c = '*') or + (c = '$') or (c = '%'); +end; + +function ConvertAlphaToNumber(const s: String): String; +var + i: Integer; +begin + Result := ''; + for i := 1 to Length(s) do + begin + if CharIsInInterval(s[i], '0', '9') then + Result := Result + s[i] + else if CharIsInInterval(s[i], 'A', 'Z') then + Result := Result + IntToStr(10 + Ord(s[i]) - Ord('A')) + else + raise Exception.Create('Invalid character!'); + end; +end; + +function Modulo97(const n: String): Integer; +begin + // note: the number stored in "n" may be very large, therefore we cannot + // use the standard modulo methods; see also (German): + // http://www.pruefziffernberechnung.de/Originaldokumente/IBAN/Prufziffer_07.00.pdf + if Length(n) > 9 then + Result := Modulo97(IntToStr(Modulo97(Copy(n, 1, 9))) + Copy(n, 10, Length(n)-9)) + else + Result := StrToInt(n) mod 97; +end; + +function CheckCleanIBAN(const cleanIBAN: String): Boolean; +begin + // check length + if Length(cleanIBAN) > 34 then + begin + Result := false; + Exit; + end; + + // correct check digits? + try + Result := (SEPAModulo97(Copy(cleanIBAN, 5, Length(cleanIBAN)) + Copy(cleanIBAN, 1, 4)) = 1); + except + // invalid characters detected + Result := false; + end; +end; + +function CheckCleanBIC(const cleanBIC: String): Boolean; +var + i: Integer; +begin + // check length + Result := (Length(cleanBIC) = 8) or (Length(cleanBIC) = 11); + + // check characters + if Result then + begin + for i := 1 to Length(cleanBIC) do + begin + if not CharIsInInterval(cleanBIC[i], '0', '9') and + not CharIsInInterval(cleanBIC[i], 'A', 'Z') then + begin + Result := false; + Break; + end; + end; + end; +end; + +function CheckCleanCI(const cleanCI: String): Boolean; +begin + // check length + if Length(cleanCI) > 35 then + begin + Result := false; + Exit; + end; + + // correct check digits? + try + Result := (SEPAModulo97(Copy(cleanCI, 8, Length(cleanCI)) + Copy(cleanCI, 1, 4)) = 1); + except + // invalid characters detected + Result := false; + end; +end; + +function IsGermanIBAN(const cleanIBAN: String): Boolean; +begin + Result := (Copy(cleanIBAN, 1, 2) = COUNTRY_CODE_DE); +end; + +procedure WriteString(const stream: TStream; const str: String); +var + utf8: UTF8String; +begin + utf8 := StringToUTF8(str); + stream.WriteBuffer(utf8[1], Length(utf8)); +end; + +// commonly used (public) methods + +function SEPAGenerateUUID: String; +var + uid: TGuid; + res: HResult; +begin + res := CreateGuid(Uid); + if res = S_OK then + begin + Result := GuidToString(uid); + Result := StringReplace(Result, '-', '', [rfReplaceAll]); + Result := StringReplace(Result, '{', '', [rfReplaceAll]); + Result := StringReplace(Result, '}', '', [rfReplaceAll]); + end + else + Result := IntToStr(RandomRange(10000, High(Integer))); // fallback to simple random number +end; + +function SEPACleanIBANorBICorCI(s: String): String; +begin + // note: AnsiUpperCase works on Unicode strings since Delphi 2009 + Result := Trim(StringReplace(AnsiUpperCase(s), ' ', '', [rfReplaceAll])); +end; + +function SEPAModulo97(const str: String): Integer; +var + n: String; +begin + n := ConvertAlphaToNumber(str); + if n = '' then + Result := 0 + else + Result := Modulo97(n); +end; + +function SEPACheckIBAN(const iban: String): Boolean; +begin + Result := CheckCleanIBAN(SEPACleanIBANorBICorCI(iban)); +end; + +function SEPACheckBIC(const bic: String): Boolean; +begin + Result := CheckCleanBIC(SEPACleanIBANorBICorCI(bic)); +end; + +function SEPACheckCI(const ci: String): Boolean; +begin + Result := CheckCleanCI(SEPACleanIBANorBICorCI(ci)); +end; + +function SEPAIsGermanIBAN(const iban: String): Boolean; +begin + Result := IsGermanIBAN(SEPACleanIBANorBICorCI(iban)); +end; + +function SEPACleanString(const s: String; const maxlen: Integer = -1): String; +var + i: Integer; +begin + Result := s; + for i := 1 to Length(Result) do + begin + if not CharIsSEPAWhitelisted(Result[i]) then + begin + if (SEPASupportSpecialChars and CharIsGermanSpecialChar(Result[i])) then + begin + // some special characters are allowed in "pain.008.003.02", do not convert + // them if "SupportGermanSpecialChars" is set + end + else + begin + // use "EPC Best Practices" to convert characters that were allowed in + // the old DTAUS files + if Result[i] = 'Ä' then Result[i] := 'A' + else if Result[i] = 'Ö' then Result[i] := 'O' + else if Result[i] = 'Ü' then Result[i] := 'U' + else if Result[i] = 'ä' then Result[i] := 'a' + else if Result[i] = 'ö' then Result[i] := 'o' + else if Result[i] = 'ü' then Result[i] := 'u' + else if Result[i] = 'ß' then Result[i] := 's' + else if Result[i] = '&' then Result[i] := '+' + else if Result[i] = '*' then Result[i] := '.' + else if Result[i] = '$' then Result[i] := '.' + else if Result[i] = '%' then Result[i] := '.' + else Result[i] := ' '; + end; + end; + end; + if (maxlen >= 0) and (Length(Result) > maxlen) then + Result := Copy(Result, 1, maxlen); +end; + +function SEPACheckString(const s: String; const maxlen: Integer = -1): Boolean; +begin + Result := (SEPACleanString(s, maxlen) = s); +end; + +function SEPACheckRounded(const d: Currency): Boolean; +begin + // check that the given value is rounded to two decimal places; + // currency values have exactly four decimal places, just use a string + // comparison after formatting (once after rounding) - not exactly + // elegant, but works + Result := (CurrToStrF(d, ffFixed, 4) = CurrToStrF(SimpleRoundTo(d, -2), ffFixed, 2)+'00'); +end; + +function SEPAFormatAmount(const d: Currency; const digits: Integer = 2): String; +{$IFDEF FormatSettings} +begin + Result := CurrToStrF(d, ffFixed, digits, SEPAFormatSettings); +end; +{$ELSE} +var + OldDecimalSeparator: Char; +begin + OldDecimalSeparator := DecimalSeparator; // note: not thread-safe + DecimalSeparator := '.'; + Result := CurrToStrF(d, ffFixed, digits); + DecimalSeparator := OldDecimalSeparator; +end; +{$ENDIF} + +function SEPAFormatBoolean(const b: Boolean): String; +begin + Result := IfThen(b, SEPA_TRUE, SEPA_FALSE); +end; + +function SEPAFormatDate(const d: TDateTime): String; +begin + Result := FormatDateTime('yyyy"-"mm"-"dd', d); +end; + +function SEPAFormatDateTime(const d: TDateTime): String; +begin + Result := FormatDateTime('yyyy"-"mm"-"dd"T"hh":"nn":"ss"."zzz"Z"', d); +end; + +procedure SEPAWriteLine(const stream: TStream; const line: String); +begin + WriteString(stream, line); + WriteString(stream, sLineBreak); +end; + +// TFinancialInstitution + +procedure TFinancialInstitution.SetBIC(const str: String); +begin + fBIC := SEPACleanIBANorBICorCI(str); +end; + +function TFinancialInstitution.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + if (BIC = '') and (OthrID = '') then + Result.Append(EMPTY_BIC_OTHR_ID); + + if (BIC <> '') and (OthrID <> '') then + Result.Append(BOTH_BIC_OTHR_ID); + + if (BIC <> '') and not SEPACheckBIC(BIC) then + Result.Append(Format(INVALID_BIC, [BIC])); + + if (OthrID <> '') and (OthrID <> FIN_INSTN_NOTPROVIDED) then + Result.Append(INVALID_OTHR_ID); + + if (schema = SCHEMA_PAIN_001_002_03) or (schema = SCHEMA_PAIN_008_002_02) then + begin + // IBAN-only not oallowed: + + if (BIC = '') and (OthrID <> '') then + Result.Append(IBAN_ONLY_NOT_ALLOWED); + end; +end; + +procedure TFinancialInstitution.SaveToStream(const stream: TStream; const schema: String); +begin + if (BIC = '') and (OthrID <> '') then + SEPAWriteLine(stream, ''+SEPACleanString(OthrID)+'') + else + SEPAWriteLine(stream, ''+SEPACleanString(BIC)+''); +end; + +// TAccountIdentification + +procedure TAccountIdentification.SetIBAN(const str: String); +begin + fIBAN := SEPACleanIBANorBICorCI(str); +end; + +function TAccountIdentification.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + if IBAN = '' then + Result.Append(EMPTY_IBAN); + + if (IBAN <> '') and not SEPACheckIBAN(IBAN) then + Result.Append(Format(INVALID_IBAN, [IBAN])); +end; + +procedure TAccountIdentification.SaveToStream(const stream: TStream; const schema: String); +begin + SEPAWriteLine(stream, ''+SEPACleanString(IBAN)+''); +end; + +{$IFDEF FormatSettings} +initialization + // initialize format settings variable with correct decimal separator + SEPAFormatSettings := DefaultFormatSettings; + SEPAFormatSettings.DecimalSeparator := '.'; +{$ENDIF} + +end. diff --git a/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACreditTransfer.dcu b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPACreditTransfer.dcu new file mode 100644 index 0000000000000000000000000000000000000000..2b6bdaf70d7f4ab57c2de70af42dcf66c669d556 GIT binary patch literal 21535 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 TCreditTransferInitiation + // TCreditTransferInitiation + // TCreditTransferPaymentInformation + // TCreditTransferTransactionInformation + // ... + // ... + // + // ... + // + // Note that all strings in these units are interpreted with respect to the + // default behavior of the development environment, i.e., + // a) for Delphi < 2009: ANSI strings + // b) for Delphi >= 2009: Unicode strings + // c) for Lazarus: no encoding specified, ANSI is assumed + + TCreditTransferTransactionInformation = class + private + fPmtIdEndToEndId: String; // end-to-end identification of this payment (by default "NOTPROVIDED") + fInstdAmtCcy: String; // instructed amount, currency (always "EUR") + fInstdAmt: Currency; // instructed amount + fCdtrAgt: TFinancialInstitution; // creditor agent + fCdtrNm: String; // creditor name + fCdtrAcct: TAccountIdentification; // creditor account identification + fRmtInfUstrd: String; // unstructured remittance information + + procedure SetCdtrNm(const str: String); + procedure SetRmtInfUstrd(const str: String); + public + constructor Create; + destructor Destroy; override; + + property PmtIdEndToEndId: String read fPmtIdEndToEndId write fPmtIdEndToEndId; + property InstdAmtCcy: String read fInstdAmtCcy write fInstdAmtCcy; + property InstdAmt: Currency read fInstdAmt write fInstdAmt; + property CdtrAgt: TFinancialInstitution read fCdtrAgt; + property CdtrNm: String read fCdtrNm write SetCdtrNm; + property CdtrAcct: TAccountIdentification read fCdtrAcct; + property RmtInfUstrd: String read fRmtInfUstrd write SetRmtInfUstrd; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TCreditTransferPaymentInformation = class + private + fPmtInfId: String; // payment information identification + fPmtMtd: String; // payment method (always "TRF") + fPmtTpInfSvcLvlCd: String; // payment type, service level code (always "SEPA") + fPmtTpInfInstrPrty: String; // payment type, instruction priority ("NORM" or "HIGH") + fReqdExctnDt: TDateTime; // requested execution date + fDbtrNm: String; // creditor name + fDbtrAcct: TAccountIdentification; // creditor account identification + fDbtrAgt: TFinancialInstitution; // creditor agent + fChrgBr: String; // charge bearer (always "SLEV") + fCdtTrfTxInf: array of TCreditTransferTransactionInformation; + + procedure SetDbtrNm(const str: String); + + function GetCtrlSum: Currency; + function GetCdtTrfTxInfEntry(const i: Integer): TCreditTransferTransactionInformation; + function GetCdtTrfTxInfCount: Integer; + public + constructor Create; + destructor Destroy; override; + + property PmtInfId: String read fPmtInfId write fPmtInfId; + property PmtMtd: String read fPmtMtd write fPmtMtd; + property NbOfTxs: Integer read GetCdtTrfTxInfCount; + property CtrlSum: Currency read GetCtrlSum; + property PmtTpInfSvcLvlCd: String read fPmtTpInfSvcLvlCd write fPmtTpInfSvcLvlCd; + property PmtTpInfInstrPrty: String read fPmtTpInfInstrPrty write fPmtTpInfInstrPrty; + property ReqdExctnDt: TDateTime read fReqdExctnDt write fReqdExctnDt; + property DbtrNm: String read fDbtrNm write SetDbtrNm; + property DbtrAcct: TAccountIdentification read fDbtrAcct; + property DbtrAgt: TFinancialInstitution read fDbtrAgt; + property ChrgBr: String read fChrgBr write fChrgBr; + + procedure AppendCdtTrfTxInfEntry(const transaction: TCreditTransferTransactionInformation); + property CdtTrfTxInfEntry[const i: Integer]: TCreditTransferTransactionInformation read GetCdtTrfTxInfEntry; + property CdtTrfTxInfCount: Integer read GetCdtTrfTxInfCount; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TCreditTransferInitiation = class + private + fSchema: String; // ISO schema, e.g. "pain.001.002.03", empty means auto-select based on date + fGrpHdrMsgId: String; // group header: message identification + fGrpHdrCreDtTm: TDateTime; // group header: time of file creation + fGrpHdrInitgPtyName: String; // group header: initiator name + fPmtInf: array of TCreditTransferPaymentInformation; + + function GetSchema: String; + procedure SetGrpHdrInitgPtyName(const str: String); + + function GetGrpHdrNbOfTxs: Integer; + function GetPmtInfEntry(const i: Integer): TCreditTransferPaymentInformation; + function GetPmtInfCount: Integer; + public + constructor Create; + destructor Destroy; override; + + property Schema: String read GetSchema write fSchema; + + property GrpHdrMsgId: String read fGrpHdrMsgId write fGrpHdrMsgId; + property GrpHdrCreDtTm: TDateTime read fGrpHdrCreDtTm write fGrpHdrCreDtTm; + property GrpHdrNbOfTxs: Integer read GetGrpHdrNbOfTxs; + property GrpHdrInitgPtyName: String read fGrpHdrInitgPtyName write SetGrpHdrInitgPtyName; + + procedure AppendPmtInfEntry(const instruction: TCreditTransferPaymentInformation); + property PmtInfEntry[const i: Integer]: TCreditTransferPaymentInformation read GetPmtInfEntry; + property PmtInfCount: Integer read GetPmtInfCount; + + function Validate(const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream); + procedure SaveToDisk(const FileName: String); + end; + +implementation + +// TCreditTransferTransactionInformation + +constructor TCreditTransferTransactionInformation.Create; +begin + inherited; + fPmtIdEndToEndId := END_TO_END_ID_NOTPROVIDED; + fInstdAmtCcy := CCY_EUR; + fCdtrAgt := TFinancialInstitution.Create; + fCdtrAcct := TAccountIdentification.Create; +end; + +destructor TCreditTransferTransactionInformation.Destroy; +begin + FreeAndNil(fCdtrAgt); + FreeAndNil(fCdtrAcct); + inherited; +end; + +procedure TCreditTransferTransactionInformation.SetCdtrNm(const str: String); +begin + fCdtrNm := SEPACleanString(str); +end; + +procedure TCreditTransferTransactionInformation.SetRmtInfUstrd(const str: String); +begin + fRmtInfUstrd := SEPACleanString(str); +end; + +function TCreditTransferTransactionInformation.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if PmtIdEndToEndId = '' then + Result.Append(EMPTY_END_TO_END_ID); + + if InstdAmtCcy = '' then + Result.Append(EMPTY_INSTD_AMT_CCY); + + if CdtrNm = '' then + Result.Append(EMPTY_CDTR_NM); + + if RmtInfUstrd = '' then + Result.Append(EMPTY_RMT_INF_USTRD); + + // check for invalid fields + + if not SEPACheckString(PmtIdEndToEndId, END_TO_END_ID_MAX_LEN) then + Result.Append(Format(INVALID_END_TO_END_ID, [PmtIdEndToEndId])); + + if (InstdAmt <= 0.0) or not SEPACheckRounded(InstdAmt) then + Result.Append(Format(INVALID_INSTD_AMT, [SEPAFormatAmount(InstdAmt, 4)])); + + if not SEPACheckString(CdtrNm, CDTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_CDTR_NM, [CdtrNm])); + + if not SEPACheckString(RmtInfUstrd, RMT_INF_USTRD_MAX_LEN) then + Result.Append(Format(INVALID_RMT_INF_USTRD, [RmtInfUstrd])); + + // delegate validations where possible + + // note: for IBAN-only, according to the specification the creditor agent + // has to be left out completely; not even NOTPROVIDED is allowed - yet, we + // handle this the same way and just do not write this block + // to the file if no BIC is given (corresponds to NOTPROVIDED flag), see also + // method SaveToStream + CdtrAgt.Validate(schema, Result); + + CdtrAcct.Validate(schema, Result); + + // plausibility checks + + if (CdtrAgt.OthrID = FIN_INSTN_NOTPROVIDED) and not SEPAIsGermanIBAN(CdtrAcct.IBAN) then + Result.Append(INVALID_IBAN_NOT_DE); +end; + +procedure TCreditTransferTransactionInformation.SaveToStream(const stream: TStream; const schema: String); +begin + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(PmtIdEndToEndId)+''); + SEPAWriteLine(stream, ''+SEPAFormatAmount(InstdAmt)+''); + + if CdtrAgt.BIC <> '' then // note: do not write block to the file if IBAN-only + begin // is required, see also comment in method Validate + SEPAWriteLine(stream, ''); + CdtrAgt.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + end; + + SEPAWriteLine(stream, ''+SEPACleanString(CdtrNm, DBTR_NM_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); + CdtrAcct.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(RmtInfUstrd, RMT_INF_USTRD_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); +end; + +// TCreditTransferPaymentInformation + +constructor TCreditTransferPaymentInformation.Create; +begin + inherited; + fPmtInfId := SEPAGenerateUUID; + fPmtMtd := PMT_MTD_CREDIT_TRANSFER; + fPmtTpInfSvcLvlCd := SEPA; + fChrgBr := CHRG_BR_SLEV; + fDbtrAcct := TAccountIdentification.Create; + fDbtrAgt := TFinancialInstitution.Create; +end; + +destructor TCreditTransferPaymentInformation.Destroy; +var + i: Integer; +begin + FreeAndNil(fDbtrAcct); + FreeAndNil(fDbtrAgt); + for i := Low(fCdtTrfTxInf) to High(fCdtTrfTxInf) do + FreeAndNil(fCdtTrfTxInf[i]); + inherited; +end; + +procedure TCreditTransferPaymentInformation.SetDbtrNm(const str: String); +begin + fDbtrNm := SEPACleanString(str); +end; + +function TCreditTransferPaymentInformation.GetCtrlSum: Currency; +var + i: Integer; +begin + Result := 0.0; + for i := 0 to CdtTrfTxInfCount-1 do + Result := Result + CdtTrfTxInfEntry[i].InstdAmt; +end; + +procedure TCreditTransferPaymentInformation.AppendCdtTrfTxInfEntry(const transaction: TCreditTransferTransactionInformation); +var + i: Integer; +begin + i := Length(fCdtTrfTxInf); + SetLength(fCdtTrfTxInf, i+1); + fCdtTrfTxInf[i] := transaction; +end; + +function TCreditTransferPaymentInformation.GetCdtTrfTxInfEntry(const i: Integer): TCreditTransferTransactionInformation; +begin + Result := fCdtTrfTxInf[i]; +end; + +function TCreditTransferPaymentInformation.GetCdtTrfTxInfCount: Integer; +begin + Result := Length(fCdtTrfTxInf); +end; + +function TCreditTransferPaymentInformation.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +var + i: Integer; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if PmtInfId = '' then + Result.Append(EMPTY_PMT_INF_ID); + + if DbtrNm = '' then + Result.Append(EMPTY_DBTR_NM); + + // check for invalid fields + + if not SEPACheckString(PmtInfId, ID_MAX_LEN) then + Result.Append(Format(INVALID_PMT_INF_ID, [PmtInfId])); + + if PmtMtd <> PMT_MTD_CREDIT_TRANSFER then + Result.Append(Format(INVALID_PMT_MTD, [PmtMtd])); + + if Trunc(ReqdExctnDt) < Today then + Result.Append(Format(INVALID_REQD_EXCTN_DT, [DateToStr(ReqdExctnDt)])); + + if PmtTpInfSvcLvlCd <> SEPA then + Result.Append(Format(INVALID_SVC_LVL_CD, [PmtTpInfSvcLvlCd])); + + if (PmtTpInfInstrPrty <> '') and (PmtTpInfInstrPrty <> INSTR_PRTY_NORM) and (PmtTpInfInstrPrty <> INSTR_PRTY_HIGH) then + Result.Append(Format(INVALID_INSTR_PRTY, [PmtTpInfInstrPrty])); + + if ChrgBr <> CHRG_BR_SLEV then + Result.Append(Format(INVALID_CHRG_BR, [ChrgBr])); + + if not SEPACheckString(DbtrNm, DBTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_DBTR_NM, [DbtrNm])); + + // delegate validations where possible + + DbtrAcct.Validate(schema, Result); + DbtrAgt.Validate(schema, Result); + + for i := 0 to CdtTrfTxInfCount-1 do + CdtTrfTxInfEntry[i].Validate(schema, Result); + + // plausibility checks + + if not SEPAIsGermanIBAN(DbtrAcct.IBAN) then + Result.Append(INVALID_DBTR_ACCT_NOT_DE); + + // note: number of objects in DrctDbtTxInf is not checked - if empty, then this + // object will be ignored by TCreditTransferInitiation; and TCreditTransferInitiation + // ensures in its validation that it has some transactions +end; + +procedure TCreditTransferPaymentInformation.SaveToStream(const stream: TStream; const schema: String); +var + i: Integer; +begin + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(PmtInfId)+''); + SEPAWriteLine(stream, ''+SEPACleanString(PmtMtd)+''); + SEPAWriteLine(stream, ''+IntToStr(NbOfTxs)+''); + SEPAWriteLine(stream, ''+SEPAFormatAmount(CtrlSum)+''); + + SEPAWriteLine(stream, ''); + if PmtTpInfInstrPrty <> '' then + SEPAWriteLine(stream, ''+SEPACleanString(PmtTpInfInstrPrty)+''); + SEPAWriteLine(stream, ''+SEPACleanString(PmtTpInfSvcLvlCd)+''); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPAFormatDate(ReqdExctnDt)+''); + SEPAWriteLine(stream, ''+SEPACleanString(DbtrNm, DBTR_NM_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); + DbtrAcct.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''); + DbtrAgt.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(ChrgBr)+''); + + for i := 0 to CdtTrfTxInfCount-1 do + CdtTrfTxInfEntry[i].SaveToStream(stream, schema); + + SEPAWriteLine(stream, ''); +end; + +// TCreditTransferInitiation + +constructor TCreditTransferInitiation.Create; +begin + inherited; + fSchema := ''; // empty = auto-select + fGrpHdrMsgId := SEPAGenerateUUID; + fGrpHdrCreDtTm := Now; +end; + +destructor TCreditTransferInitiation.Destroy; +var + i: Integer; +begin + for i := Low(fPmtInf) to High(fPmtInf) do + FreeAndNil(fPmtInf[i]); + inherited; +end; + +function TCreditTransferInitiation.GetSchema: String; +begin + Result := fSchema; + if Result = '' then + Result := SCHEMA_PAIN_001_003_03 +end; + +procedure TCreditTransferInitiation.SetGrpHdrInitgPtyName(const str: String); +begin + fGrpHdrInitgPtyName := SEPACleanString(str); +end; + +function TCreditTransferInitiation.GetGrpHdrNbOfTxs: Integer; +var + i: Integer; +begin + Result := 0; + for i := 0 to PmtInfCount-1 do + Inc(Result, PmtInfEntry[i].NbOfTxs); +end; + +procedure TCreditTransferInitiation.AppendPmtInfEntry(const instruction: TCreditTransferPaymentInformation); +var + i: Integer; +begin + i := Length(fPmtInf); + SetLength(fPmtInf, i+1); + fPmtInf[i] := instruction; +end; + +function TCreditTransferInitiation.GetPmtInfEntry(const i: Integer): TCreditTransferPaymentInformation; +begin + Result := fPmtInf[i]; +end; + +function TCreditTransferInitiation.GetPmtInfCount: Integer; +begin + Result := Length(fPmtInf); +end; + +function TCreditTransferInitiation.Validate(const appendTo: TStringList = nil): TStringList; +var + i: Integer; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check ISO schema + + if (Schema <> SCHEMA_PAIN_001_002_03) and (Schema <> SCHEMA_PAIN_001_003_03) then + Result.Append(Format(UNKNOWN_SCHEMA, [Schema])); + + // check for empty fields + + if GrpHdrMsgId = '' then + Result.Append(EMPTY_GRP_HDR_MSG_ID); + + if GrpHdrInitgPtyName = '' then + Result.Append(EMPTY_INITG_PTY_NAME); + + // check for invalid fields + + if not SEPACheckString(GrpHdrMsgId, ID_MAX_LEN) then + Result.Append(Format(INVALID_GRP_HDR_MSG_ID, [GrpHdrMsgId])); + + if not SEPACheckString(GrpHdrInitgPtyName, INITG_PTY_NAME_MAX_LEN) then + Result.Append(Format(INVALID_INITG_PTY_NAME, [GrpHdrInitgPtyName])); + + // delegate validations where possible + + for i := 0 to PmtInfCount-1 do + PmtInfEntry[i].Validate(Schema, Result); + + // plausibility checks + + if GrpHdrNbOfTxs = 0 then + Result.Append(INVALID_NB_OF_TXS); +end; + +procedure TCreditTransferInitiation.SaveToStream(const stream: TStream); +var + i: Integer; +begin + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''+SEPACleanString(GrpHdrMsgId)+''); + SEPAWriteLine(stream, ''+SEPAFormatDateTime(GrpHdrCreDtTm)+''); + SEPAWriteLine(stream, ''+IntToStr(GrpHdrNbOfTxs)+''); + SEPAWriteLine(stream, ''+SEPACleanString(GrpHdrInitgPtyName, INITG_PTY_NAME_MAX_LEN)+''); + SEPAWriteLine(stream, ''); + + for i := 0 to PmtInfCount-1 do + if PmtInfEntry[i].NbOfTxs > 0 then + PmtInfEntry[i].SaveToStream(stream, Schema); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); +end; + +procedure TCreditTransferInitiation.SaveToDisk(const FileName: String); +var + stream: TMemoryStream; +begin + stream := TMemoryStream.Create; + try + SaveToStream(stream); + stream.SaveToFile(FileName); + finally + stream.Free; + end; +end; + +end. diff --git a/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPADirectDebit.dcu b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/SEPADirectDebit.dcu new file mode 100644 index 0000000000000000000000000000000000000000..19d02e6fc387e6aa348494f3583ec1b7217d6271 GIT binary patch literal 33353 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 uJ!h2|*T@C>I TDirectDebitInitiation + // TDirectDebitInitiation + // TDirectDebitPaymentInformation + // TDirectDebitTransactionInformation + // TMandateRelatedInformation + // TAmendmentInformationDetails + // ... + // ... + // + // ... + // + // Note that all strings in these units are interpreted with respect to the + // default behavior of the development environment, i.e., + // a) for Delphi < 2009: ANSI strings + // b) for Delphi >= 2009: Unicode strings + // c) for Lazarus: no encoding specified, ANSI is assumed + + TAmendmentInformationDetails = class + private + fOrgnlMndtId: String; // original mandate identification + fOrgnlCdtrSchmeIdNm: String; // original creditor name + fOrgnlCdtrSchmeIdIdPrvtIdOthrId: String; // original creditor identifier + fOrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry: String; // (always "SEPA") + fOrgnlDbtrAcct: TAccountIdentification; // original debtor account identification + fOrgnlDbtrAgtFinInstIdOthrId: String; // "SMNDA" if same mandate + new debtor agent + + procedure SetOrgnlCdtrSchmeIdIdPrvtIdOthrId(const str: String); + public + constructor Create; + destructor Destroy; override; + + property OrgnlMndtId: String read fOrgnlMndtId write fOrgnlMndtId; + property OrgnlCdtrSchmeIdNm: String read fOrgnlCdtrSchmeIdNm write fOrgnlCdtrSchmeIdNm; + property OrgnlCdtrSchmeIdIdPrvtIdOthrId: String read fOrgnlCdtrSchmeIdIdPrvtIdOthrId write SetOrgnlCdtrSchmeIdIdPrvtIdOthrId; + property OrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry: String read fOrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry write fOrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry; + property OrgnlDbtrAcct: TAccountIdentification read fOrgnlDbtrAcct; + property OrgnlDbtrAgtFinInstIdOthrId: String read fOrgnlDbtrAgtFinInstIdOthrId write fOrgnlDbtrAgtFinInstIdOthrId; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TMandateRelatedInformation = class + private + fMndtId: String; // mandate identification + fDtOfSgntr: TDateTime; // date of signature + fAmdmntInd: Boolean; // amendment indicator ("false" or "true") + fAmdmntInfDtls: TAmendmentInformationDetails; + public + constructor Create; + destructor Destroy; override; + + property MndtId: String read fMndtId write fMndtId; + property DtOfSgntr: TDateTime read fDtOfSgntr write fDtOfSgntr; + property AmdmntInd: Boolean read fAmdmntInd write fAmdmntInd; + property AmdmntInfDtls: TAmendmentInformationDetails read fAmdmntInfDtls; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TDirectDebitTransactionInformation = class + private + fPmtIdEndToEndId: String; // end-to-end identification of this payment (by default "NOTPROVIDED") + fInstdAmtCcy: String; // instructed amount, currency (always "EUR") + fInstdAmt: Currency; // instructed amount + fDrctDbtTxMndtRltdInf: TMandateRelatedInformation; + fDbtrAgt: TFinancialInstitution; // debtor agent + fDbtrNm: String; // debtor name + fDbtrAcct: TAccountIdentification; // debtor account identification + fUltmtDbtrNm: String; // ultimate debtor name (optional) + fRmtInfUstrd: String; // unstructured remittance information + + procedure SetDbtrNm(const str: String); + procedure SetUltmtDbtrNm(const str: String); + procedure SetRmtInfUstrd(const str: String); + public + constructor Create; + destructor Destroy; override; + + property PmtIdEndToEndId: String read fPmtIdEndToEndId write fPmtIdEndToEndId; + property InstdAmtCcy: String read fInstdAmtCcy write fInstdAmtCcy; + property InstdAmt: Currency read fInstdAmt write fInstdAmt; + property DrctDbtTxMndtRltdInf: TMandateRelatedInformation read fDrctDbtTxMndtRltdInf; + property DbtrAgt: TFinancialInstitution read fDbtrAgt; + property DbtrNm: String read fDbtrNm write SetDbtrNm; + property DbtrAcct: TAccountIdentification read fDbtrAcct; + property UltmtDbtrNm: String read fUltmtDbtrNm write SetUltmtDbtrNm; + property RmtInfUstrd: String read fRmtInfUstrd write SetRmtInfUstrd; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TDirectDebitPaymentInformation = class + private + fPmtInfId: String; // payment information identification + fPmtMtd: String; // payment method (always "DD") + fPmtTpInfSvcLvlCd: String; // payment type, service level code (always "SEPA") + fPmtTpInfLclInstrmCd: String; // payment type, local instrument code ("CORE", "COR1" or "B2B") + fPmtTpInfSeqTp: String; // payment type, sequence type ("FRST", "RCUR", "OOFF" or "FNAL") + fReqdColltnDt: TDateTime; // requested collection date + fCdtrNm: String; // creditor name + fCdtrAcct: TAccountIdentification; // creditor account identification + fCdtrAgt: TFinancialInstitution; // creditor agent + fChrgBr: String; // charge bearer (always "SLEV") + fCdtrSchmeIdIdPrvtIdOthrId: String; // creditor identifier + fCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry: String; // proprietary (always "SEPA") + fDrctDbtTxInf: array of TDirectDebitTransactionInformation; + + procedure SetCdtrNm(const str: String); + procedure SetCdtrSchmeIdIdPrvtIdOthrId(const str: String); + + function GetCtrlSum: Currency; + function GetDrctDbtTxInfEntry(const i: Integer): TDirectDebitTransactionInformation; + function GetDrctDbtTxInfCount: Integer; + public + constructor Create; + destructor Destroy; override; + + property PmtInfId: String read fPmtInfId write fPmtInfId; + property PmtMtd: String read fPmtMtd write fPmtMtd; + property NbOfTxs: Integer read GetDrctDbtTxInfCount; + property CtrlSum: Currency read GetCtrlSum; + property PmtTpInfSvcLvlCd: String read fPmtTpInfSvcLvlCd write fPmtTpInfSvcLvlCd; + property PmtTpInfLclInstrmCd: String read fPmtTpInfLclInstrmCd write fPmtTpInfLclInstrmCd; + property PmtTpInfSeqTp: String read fPmtTpInfSeqTp write fPmtTpInfSeqTp; + property ReqdColltnDt: TDateTime read fReqdColltnDt write fReqdColltnDt; + property CdtrNm: String read fCdtrNm write SetCdtrNm; + property CdtrAcct: TAccountIdentification read fCdtrAcct; + property CdtrAgt: TFinancialInstitution read fCdtrAgt; + property ChrgBr: String read fChrgBr write fChrgBr; + property CdtrSchmeIdIdPrvtIdOthrId: String read fCdtrSchmeIdIdPrvtIdOthrId write SetCdtrSchmeIdIdPrvtIdOthrId; + property CdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry: String read fCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry write fCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry; + + procedure AppendDrctDbtTxInfEntry(const transaction: TDirectDebitTransactionInformation); + property DrctDbtTxInfEntry[const i: Integer]: TDirectDebitTransactionInformation read GetDrctDbtTxInfEntry; + property DrctDbtTxInfCount: Integer read GetDrctDbtTxInfCount; + + function Validate(const schema: String; const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream; const schema: String); + end; + + TDirectDebitInitiation = class + private + fSchema: String; // ISO schema, e.g. "pain.008.002.02", empty means auto-select based on date and COR1 + fGrpHdrMsgId: String; // group header: message identification + fGrpHdrCreDtTm: TDateTime; // group header: time of file creation + fGrpHdrInitgPtyName: String; // group header: initiator name + fPmtInf: array of TDirectDebitPaymentInformation; + + function GetSchema: String; + procedure SetGrpHdrInitgPtyName(const str: String); + + function GetGrpHdrNbOfTxs: Integer; + function GetPmtInfEntry(const i: Integer): TDirectDebitPaymentInformation; + function GetPmtInfCount: Integer; + public + constructor Create; + destructor Destroy; override; + + property Schema: String read GetSchema write fSchema; + + property GrpHdrMsgId: String read fGrpHdrMsgId write fGrpHdrMsgId; + property GrpHdrCreDtTm: TDateTime read fGrpHdrCreDtTm write fGrpHdrCreDtTm; + property GrpHdrNbOfTxs: Integer read GetGrpHdrNbOfTxs; + property GrpHdrInitgPtyName: String read fGrpHdrInitgPtyName write SetGrpHdrInitgPtyName; + + procedure AppendPmtInfEntry(const instruction: TDirectDebitPaymentInformation); + property PmtInfEntry[const i: Integer]: TDirectDebitPaymentInformation read GetPmtInfEntry; + property PmtInfCount: Integer read GetPmtInfCount; + + function Validate(const appendTo: TStringList = nil): TStringList; + procedure SaveToStream(const stream: TStream); + procedure SaveToDisk(const FileName: String); + end; + +implementation + +// TAmendmentInformationDetails + +constructor TAmendmentInformationDetails.Create; +begin + inherited; + fOrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry := SEPA; + fOrgnlDbtrAcct := TAccountIdentification.Create; +end; + +destructor TAmendmentInformationDetails.Destroy; +begin + FreeAndNil(fOrgnlDbtrAcct); + inherited; +end; + +procedure TAmendmentInformationDetails.SetOrgnlCdtrSchmeIdIdPrvtIdOthrId(const str: String); +begin + fOrgnlCdtrSchmeIdIdPrvtIdOthrId := SEPACleanIBANorBICorCI(str); +end; + +function TAmendmentInformationDetails.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if (OrgnlMndtId = '') and (OrgnlCdtrSchmeIdNm = '') and (OrgnlCdtrSchmeIdIdPrvtIdOthrId = '') and + (OrgnlDbtrAcct.IBAN = '') and (OrgnlDbtrAgtFinInstIdOthrId = '') then + Result.Append(EMPTY_AMDMNT_INF_DTLS); + + // check for invalid fields + + if not SEPACheckString(OrgnlMndtId, MNDT_ID_MAX_LEN) then + Result.Append(Format(INVALID_ORGNL_MNDT_ID, [OrgnlMndtId])); + + if not SEPACheckString(OrgnlCdtrSchmeIdNm, CDTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_ORGNL_CRDTR_NM, [OrgnlCdtrSchmeIdNm])); + + if (OrgnlCdtrSchmeIdIdPrvtIdOthrId <> '') and not SEPACheckCI(OrgnlCdtrSchmeIdIdPrvtIdOthrId) then + Result.Append(Format(INVALID_ORGNL_CRDTR_ID, [OrgnlCdtrSchmeIdIdPrvtIdOthrId])); + + if OrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry <> SEPA then + Result.Append(Format(INVALID_ORGNL_CRDTR_PRTRY, [OrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry])); + + if (OrgnlDbtrAgtFinInstIdOthrId <> '') and (OrgnlDbtrAgtFinInstIdOthrId <> ORGNL_DBTR_AGT_SMNDA) then + Result.Append(Format(INVALID_ORGNL_FIN_INST_ID, [OrgnlDbtrAgtFinInstIdOthrId])); + + // delegate validations where possible + + if (OrgnlDbtrAcct.IBAN <> '') then + OrgnlDbtrAcct.Validate(schema, Result); +end; + +procedure TAmendmentInformationDetails.SaveToStream(const stream: TStream; const schema: String); +begin + SEPAWriteLine(stream, ''); + + if OrgnlMndtId <> '' then + SEPAWriteLine(stream, ''+SEPACleanString(OrgnlMndtId)+''); + + if (OrgnlCdtrSchmeIdNm <> '') or (OrgnlCdtrSchmeIdIdPrvtIdOthrId <> '') then + begin + SEPAWriteLine(stream, ''); + if OrgnlCdtrSchmeIdNm <> '' then + SEPAWriteLine(stream, ''+SEPACleanString(OrgnlCdtrSchmeIdNm, CDTR_NM_MAX_LEN)+''); + if OrgnlCdtrSchmeIdIdPrvtIdOthrId <> '' then + SEPAWriteLine(stream, ''+ + ''+SEPACleanString(OrgnlCdtrSchmeIdIdPrvtIdOthrId)+''+ + ''+SEPACleanString(OrgnlCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry)+''+ + ''); + SEPAWriteLine(stream, ''); + end; + + if OrgnlDbtrAcct.IBAN <> '' then + begin + SEPAWriteLine(stream, ''); + OrgnlDbtrAcct.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + end; + + if OrgnlDbtrAgtFinInstIdOthrId <> '' then + SEPAWriteLine(stream, ''+SEPACleanString(OrgnlDbtrAgtFinInstIdOthrId)+''); + + SEPAWriteLine(stream, ''); +end; + +// TMandateRelatedInformation + +constructor TMandateRelatedInformation.Create; +begin + inherited; + fAmdmntInfDtls := TAmendmentInformationDetails.Create; +end; + +destructor TMandateRelatedInformation.Destroy; +begin + FreeAndNil(fAmdmntInfDtls); + inherited; +end; + +function TMandateRelatedInformation.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if MndtId = '' then + Result.Append(EMPTY_MNDT_ID); + + if Trunc(DtOfSgntr) = 0 then + Result.Append(EMPTY_DT_OF_SGNTR); + + // check for invalid fields + + if not SEPACheckString(MndtId, MNDT_ID_MAX_LEN) then + Result.Append(Format(INVALID_MNDT_ID, [MndtId])); + + if Trunc(DtOfSgntr) > Trunc(Today) then + Result.Append(Format(INVALID_DT_OF_SGNTR, [DateToStr(DtOfSgntr)])); + + // delegate validations where possible + + if AmdmntInd then + AmdmntInfDtls.Validate(schema, Result); +end; + +procedure TMandateRelatedInformation.SaveToStream(const stream: TStream; const schema: String); +begin + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''+SEPACleanString(MndtId, MNDT_ID_MAX_LEN)+''); + SEPAWriteLine(stream, ''+SEPAFormatDate(DtOfSgntr)+''); + SEPAWriteLine(stream, ''+SEPAFormatBoolean(AmdmntInd)+''); + if AmdmntInd then + AmdmntInfDtls.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); +end; + +// TDirectDebitTransactionInformation + +constructor TDirectDebitTransactionInformation.Create; +begin + inherited; + fPmtIdEndToEndId := END_TO_END_ID_NOTPROVIDED; + fInstdAmtCcy := CCY_EUR; + fDrctDbtTxMndtRltdInf := TMandateRelatedInformation.Create; + fDbtrAgt := TFinancialInstitution.Create; + fDbtrAcct := TAccountIdentification.Create; +end; + +destructor TDirectDebitTransactionInformation.Destroy; +begin + FreeAndNil(fDrctDbtTxMndtRltdInf); + FreeAndNil(fDbtrAgt); + FreeAndNil(fDbtrAcct); + inherited; +end; + +procedure TDirectDebitTransactionInformation.SetDbtrNm(const str: String); +begin + fDbtrNm := SEPACleanString(str); +end; + +procedure TDirectDebitTransactionInformation.SetUltmtDbtrNm(const str: String); +begin + fUltmtDbtrNm := SEPACleanString(str); +end; + +procedure TDirectDebitTransactionInformation.SetRmtInfUstrd(const str: String); +begin + fRmtInfUstrd := SEPACleanString(str); +end; + +function TDirectDebitTransactionInformation.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if PmtIdEndToEndId = '' then + Result.Append(EMPTY_END_TO_END_ID); + + if InstdAmtCcy = '' then + Result.Append(EMPTY_INSTD_AMT_CCY); + + if DbtrNm = '' then + Result.Append(EMPTY_DBTR_NM); + + if RmtInfUstrd = '' then + Result.Append(EMPTY_RMT_INF_USTRD); + + // check for invalid fields + + if not SEPACheckString(PmtIdEndToEndId, END_TO_END_ID_MAX_LEN) then + Result.Append(Format(INVALID_END_TO_END_ID, [PmtIdEndToEndId])); + + if (InstdAmt <= 0.0) or not SEPACheckRounded(InstdAmt) then + Result.Append(Format(INVALID_INSTD_AMT, [SEPAFormatAmount(InstdAmt, 4)])); + + if not SEPACheckString(DbtrNm, DBTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_DBTR_NM, [DbtrNm])); + + if not SEPACheckString(UltmtDbtrNm, DBTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_ULTMT_DBTR_NM, [UltmtDbtrNm])); + + if not SEPACheckString(RmtInfUstrd, RMT_INF_USTRD_MAX_LEN) then + Result.Append(Format(INVALID_RMT_INF_USTRD, [RmtInfUstrd])); + + // delegate validations where possible + + DbtrAgt.Validate(schema, Result); + DbtrAcct.Validate(schema, Result); + DrctDbtTxMndtRltdInf.Validate(schema, Result); + + // plausibility checks + + if (DbtrAgt.OthrID = FIN_INSTN_NOTPROVIDED) and not SEPAIsGermanIBAN(DbtrAcct.IBAN) then + Result.Append(INVALID_IBAN_NOT_DE); +end; + +procedure TDirectDebitTransactionInformation.SaveToStream(const stream: TStream; const schema: String); +begin + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(PmtIdEndToEndId)+''); + SEPAWriteLine(stream, ''+SEPAFormatAmount(InstdAmt)+''); + + SEPAWriteLine(stream, ''); + DrctDbtTxMndtRltdInf.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''); + DbtrAgt.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(DbtrNm, DBTR_NM_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); + DbtrAcct.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + if UltmtDbtrNm <> '' then + SEPAWriteLine(stream, ''+SEPACleanString(UltmtDbtrNm, DBTR_NM_MAX_LEN)+''); + + SEPAWriteLine(stream, ''+SEPACleanString(RmtInfUstrd, RMT_INF_USTRD_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); +end; + +// TDirectDebitPaymentInformation + +constructor TDirectDebitPaymentInformation.Create; +begin + inherited; + fPmtInfId := SEPAGenerateUUID; + fPmtMtd := PMT_MTD_DIRECT_DEBIT; + fPmtTpInfSvcLvlCd := SEPA; + fChrgBr := CHRG_BR_SLEV; + fCdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry := SEPA; + fCdtrAcct := TAccountIdentification.Create; + fCdtrAgt := TFinancialInstitution.Create; +end; + +destructor TDirectDebitPaymentInformation.Destroy; +var + i: Integer; +begin + FreeAndNil(fCdtrAcct); + FreeAndNil(fCdtrAgt); + for i := Low(fDrctDbtTxInf) to High(fDrctDbtTxInf) do + FreeAndNil(fDrctDbtTxInf[i]); + inherited; +end; + +procedure TDirectDebitPaymentInformation.SetCdtrNm(const str: String); +begin + fCdtrNm := SEPACleanString(str); +end; + +procedure TDirectDebitPaymentInformation.SetCdtrSchmeIdIdPrvtIdOthrId(const str: String); +begin + fCdtrSchmeIdIdPrvtIdOthrId := SEPACleanIBANorBICorCI(str); +end; + +function TDirectDebitPaymentInformation.GetCtrlSum: Currency; +var + i: Integer; +begin + Result := 0.0; + for i := 0 to DrctDbtTxInfCount-1 do + Result := Result + DrctDbtTxInfEntry[i].InstdAmt; +end; + +procedure TDirectDebitPaymentInformation.AppendDrctDbtTxInfEntry(const transaction: TDirectDebitTransactionInformation); +var + i: Integer; +begin + i := Length(fDrctDbtTxInf); + SetLength(fDrctDbtTxInf, i+1); + fDrctDbtTxInf[i] := transaction; +end; + +function TDirectDebitPaymentInformation.GetDrctDbtTxInfEntry(const i: Integer): TDirectDebitTransactionInformation; +begin + Result := fDrctDbtTxInf[i]; +end; + +function TDirectDebitPaymentInformation.GetDrctDbtTxInfCount: Integer; +begin + Result := Length(fDrctDbtTxInf); +end; + +function TDirectDebitPaymentInformation.Validate(const schema: String; const appendTo: TStringList = nil): TStringList; +var + possible_reqd_colltn_dt: Cardinal; + add_days,i: Integer; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check for empty fields + + if PmtInfId = '' then + Result.Append(EMPTY_PMT_INF_ID); + + if CdtrNm = '' then + Result.Append(EMPTY_CDTR_NM); + + if CdtrSchmeIdIdPrvtIdOthrId = '' then + Result.Append(EMPTY_CDTR_ID); + + // check for invalid fields + + if not SEPACheckString(PmtInfId, ID_MAX_LEN) then + Result.Append(Format(INVALID_PMT_INF_ID, [PmtInfId])); + + if PmtMtd <> PMT_MTD_DIRECT_DEBIT then + Result.Append(Format(INVALID_PMT_MTD, [PmtMtd])); + + if (PmtTpInfLclInstrmCd <> LCL_INSTRM_CD_CORE) and + (PmtTpInfLclInstrmCd <> LCL_INSTRM_CD_COR1) and + (PmtTpInfLclInstrmCd <> LCL_INSTRM_CD_B2B) then + Result.Append(Format(INVALID_LCL_INSTRM_CD, [PmtTpInfLclInstrmCd])); + + if (PmtTpInfLclInstrmCd = LCL_INSTRM_CD_COR1) and (schema <> SCHEMA_PAIN_008_003_02) then + Result.Append(INVALID_LCL_INSTRM_CD_COR1); + + if (PmtTpInfSeqTp <> SEQ_TP_FRST) and + (PmtTpInfSeqTp <> SEQ_TP_RCUR) and + (PmtTpInfSeqTp <> SEQ_TP_OOFF) and + (PmtTpInfSeqTp <> SEQ_TP_FNAL) then + Result.Append(Format(INVALID_SEQ_TP, [PmtTpInfSeqTp])); + + // compute earliest possible date for collection (not precise: e.g. no holidays; always ask your bank for deadlines) + possible_reqd_colltn_dt := Trunc(Today); + if PmtTpInfLclInstrmCd = LCL_INSTRM_CD_CORE then + begin + if (PmtTpInfSeqTp = SEQ_TP_FRST) or (PmtTpInfSeqTp = SEQ_TP_OOFF) then + add_days := 5 + else + add_days := 2; + end + else + add_days := 1; + for i := 1 to add_days do + begin + Inc(possible_reqd_colltn_dt); + while DayOfTheWeek(possible_reqd_colltn_dt) > 5 do + Inc(possible_reqd_colltn_dt); + end; + if Trunc(ReqdColltnDt) < possible_reqd_colltn_dt then + Result.Append(Format(INVALID_REQD_COLLTN_DT, [DateToStr(ReqdColltnDt)])); + + if PmtTpInfSvcLvlCd <> SEPA then + Result.Append(Format(INVALID_SVC_LVL_CD, [PmtTpInfSvcLvlCd])); + + if ChrgBr <> CHRG_BR_SLEV then + Result.Append(Format(INVALID_CHRG_BR, [ChrgBr])); + + if not SEPACheckString(CdtrNm, CDTR_NM_MAX_LEN) then + Result.Append(Format(INVALID_CDTR_NM, [CdtrNm])); + + if not SEPACheckCI(CdtrSchmeIdIdPrvtIdOthrId) then + Result.Append(Format(INVALID_CDTR_ID, [CdtrSchmeIdIdPrvtIdOthrId])); + + if CdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry <> SEPA then + Result.Append(Format(INVALID_CDTR_PRTRY, [CdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry])); + + // delegate validations where possible + + CdtrAcct.Validate(schema, Result); + CdtrAgt.Validate(schema, Result); + + for i := 0 to DrctDbtTxInfCount-1 do + DrctDbtTxInfEntry[i].Validate(schema, Result); + + // plausibility checks + + if not SEPAIsGermanIBAN(CdtrAcct.IBAN) then + Result.Append(INVALID_CDTR_ACCT_NOT_DE); + + if PmtTpInfSeqTp = SEQ_TP_FRST then + begin + for i := 0 to DrctDbtTxInfCount-1 do + begin + if DrctDbtTxInfEntry[i].DrctDbtTxMndtRltdInf.AmdmntInd then + begin + if DrctDbtTxInfEntry[i].DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlDbtrAgtFinInstIdOthrId <> ORGNL_DBTR_AGT_SMNDA then + Result.Append(INVALID_SEQ_TP_FRST_SMNDA1); + end; + end; + end + else + begin + for i := 0 to DrctDbtTxInfCount-1 do + begin + if DrctDbtTxInfEntry[i].DrctDbtTxMndtRltdInf.AmdmntInd then + begin + if DrctDbtTxInfEntry[i].DrctDbtTxMndtRltdInf.AmdmntInfDtls.OrgnlDbtrAgtFinInstIdOthrId = ORGNL_DBTR_AGT_SMNDA then + Result.Append(INVALID_SEQ_TP_FRST_SMNDA2); + end; + end; + end; + + // note: number of objects in DrctDbtTxInf is not checked - if empty, then this + // object will be ignored by TDirectDebitInitiation; and TDirectDebitInitiation + // ensures in its validation that it has some transactions +end; + +procedure TDirectDebitPaymentInformation.SaveToStream(const stream: TStream; const schema: String); +var + i: Integer; +begin + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(PmtInfId)+''); + SEPAWriteLine(stream, ''+SEPACleanString(PmtMtd)+''); + SEPAWriteLine(stream, ''+IntToStr(NbOfTxs)+''); + SEPAWriteLine(stream, ''+SEPAFormatAmount(CtrlSum)+''); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''+SEPACleanString(PmtTpInfSvcLvlCd)+''); + SEPAWriteLine(stream, ''+SEPACleanString(PmtTpInfLclInstrmCd)+''); + SEPAWriteLine(stream, ''+SEPACleanString(fPmtTpInfSeqTp)+''); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPAFormatDate(ReqdColltnDt)+''); + SEPAWriteLine(stream, ''+SEPACleanString(CdtrNm, CDTR_NM_MAX_LEN)+''); + + SEPAWriteLine(stream, ''); + CdtrAcct.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''); + CdtrAgt.SaveToStream(stream, schema); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''+SEPACleanString(ChrgBr)+''); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''+SEPACleanString(CdtrSchmeIdIdPrvtIdOthrId)+''); + SEPAWriteLine(stream, ''+SEPACleanString(CdtrSchmeIdIdPrvtIdOthrSchmeNmPrtry)+''); + SEPAWriteLine(stream, ''); + + for i := 0 to DrctDbtTxInfCount-1 do + DrctDbtTxInfEntry[i].SaveToStream(stream, schema); + + SEPAWriteLine(stream, ''); +end; + +// TDirectDebitInitiation + +constructor TDirectDebitInitiation.Create; +begin + inherited; + fSchema := ''; // empty = auto-select + fGrpHdrMsgId := SEPAGenerateUUID; + fGrpHdrCreDtTm := Now; +end; + +destructor TDirectDebitInitiation.Destroy; +var + i: Integer; +begin + for i := Low(fPmtInf) to High(fPmtInf) do + FreeAndNil(fPmtInf[i]); + inherited; +end; + +function TDirectDebitInitiation.GetSchema: String; +begin + Result := fSchema; + if Result = '' then + Result := SCHEMA_PAIN_008_003_02; +end; + +procedure TDirectDebitInitiation.SetGrpHdrInitgPtyName(const str: String); +begin + fGrpHdrInitgPtyName := SEPACleanString(str); +end; + +function TDirectDebitInitiation.GetGrpHdrNbOfTxs: Integer; +var + i: Integer; +begin + Result := 0; + for i := 0 to PmtInfCount-1 do + Inc(Result, PmtInfEntry[i].NbOfTxs); +end; + +procedure TDirectDebitInitiation.AppendPmtInfEntry(const instruction: TDirectDebitPaymentInformation); +var + i: Integer; +begin + i := Length(fPmtInf); + SetLength(fPmtInf, i+1); + fPmtInf[i] := instruction; +end; + +function TDirectDebitInitiation.GetPmtInfEntry(const i: Integer): TDirectDebitPaymentInformation; +begin + Result := fPmtInf[i]; +end; + +function TDirectDebitInitiation.GetPmtInfCount: Integer; +begin + Result := Length(fPmtInf); +end; + +function TDirectDebitInitiation.Validate(const appendTo: TStringList = nil): TStringList; +var + FirstPmtTpInfLclInstrmCd: String; + i: Integer; +begin + if appendTo <> nil then + Result := appendTo + else + Result := TStringList.Create; + + // check ISO schema + + if (Schema <> SCHEMA_PAIN_008_002_02) and (Schema <> SCHEMA_PAIN_008_003_02) then + Result.Append(Format(UNKNOWN_SCHEMA, [Schema])); + + // check for empty fields + + if GrpHdrMsgId = '' then + Result.Append(EMPTY_GRP_HDR_MSG_ID); + + if GrpHdrInitgPtyName = '' then + Result.Append(EMPTY_INITG_PTY_NAME); + + // check for invalid fields + + if not SEPACheckString(GrpHdrMsgId, ID_MAX_LEN) then + Result.Append(Format(INVALID_GRP_HDR_MSG_ID, [GrpHdrMsgId])); + + if not SEPACheckString(GrpHdrInitgPtyName, INITG_PTY_NAME_MAX_LEN) then + Result.Append(Format(INVALID_INITG_PTY_NAME, [GrpHdrInitgPtyName])); + + // delegate validations where possible + + for i := 0 to PmtInfCount-1 do + PmtInfEntry[i].Validate(Schema, Result); + + // plausibility checks + + if GrpHdrNbOfTxs = 0 then + Result.Append(INVALID_NB_OF_TXS); + + if PmtInfCount > 0 then + begin + FirstPmtTpInfLclInstrmCd := PmtInfEntry[0].PmtTpInfLclInstrmCd; + for i := 1 to PmtInfCount-1 do + begin + if (PmtInfEntry[i].PmtTpInfLclInstrmCd <> FirstPmtTpInfLclInstrmCd) then + begin + Result.Append(INVALID_PMT_INF_MIXING); + Break; + end; + end; + end; +end; + +procedure TDirectDebitInitiation.SaveToStream(const stream: TStream); +var + i: Integer; +begin + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''+SEPACleanString(GrpHdrMsgId)+''); + SEPAWriteLine(stream, ''+SEPAFormatDateTime(GrpHdrCreDtTm)+''); + SEPAWriteLine(stream, ''+IntToStr(GrpHdrNbOfTxs)+''); + SEPAWriteLine(stream, ''+SEPACleanString(GrpHdrInitgPtyName, INITG_PTY_NAME_MAX_LEN)+''); + SEPAWriteLine(stream, ''); + + for i := 0 to PmtInfCount-1 do + if PmtInfEntry[i].NbOfTxs > 0 then + PmtInfEntry[i].SaveToStream(stream, Schema); + + SEPAWriteLine(stream, ''); + SEPAWriteLine(stream, ''); +end; + +procedure TDirectDebitInitiation.SaveToDisk(const FileName: String); +var + stream: TMemoryStream; +begin + stream := TMemoryStream.Create; + try + SaveToStream(stream); + stream.SaveToFile(FileName); + finally + stream.Free; + end; +end; + +end. diff --git a/Source/Modulos/Banca electronica/Utiles/SEPAUnit/gpl.txt b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/gpl.txt new file mode 100644 index 0000000..4914014 --- /dev/null +++ b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/gpl.txt @@ -0,0 +1,357 @@ +GNU General Public License +************************** + + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble +======== + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have +the freedom to distribute copies of free software (and charge for this +service if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone +to deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis +or for a fee, you must give the recipients all the rights that you +have. You must make sure that they, too, receive or can get the source +code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent +must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", + below, refers to any such program or work, and a "work based on + the Program" means either the Program or any derivative work under + copyright law: that is to say, a work containing the Program or a + portion of it, either verbatim or with modifications and/or + translated into another language. (Hereinafter, translation is + included without limitation in the term "modification".) Each + licensee is addressed as "you". + + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based on + the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any + warranty; and give any other recipients of the Program a copy of + this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange + for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a. You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b. You must cause any work that you distribute or publish, that + in whole or in part contains or is derived from the Program + or any part thereof, to be licensed as a whole at no charge + to all third parties under the terms of this License. + + c. If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the + program under these conditions, and telling the user how to + view a copy of this License. (Exception: if the Program + itself is interactive but does not normally print such an + announcement, your work based on the Program is not required + to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Program, the distribution of + the whole must be on the terms of this License, whose permissions + for other licensees extend to the entire whole, and thus to each + and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the + Program with the Program (or with a work based on the Program) on + a volume of a storage or distribution medium does not bring the + other work under the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms + of Sections 1 and 2 above provided that you also do one of the + following: + + a. Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Sections 1 and 2 above on a medium customarily used for + software interchange; or, + + b. Accompany it with a written offer, valid for at least three + years, to give any third-party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange; or, + + c. Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with + such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed need + not include anything that is normally distributed (in either + source or binary form) with the major components (compiler, + kernel, and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this + License. However, parties who have received copies, or rights, + from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify + or distribute the Program or its derivative works. These actions + are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any work + based on the Program), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program + subject to these terms and conditions. You may not impose any + further restrictions on the recipients' exercise of the rights + granted herein. You are not responsible for enforcing compliance + by third parties to this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent + issues), conditions are imposed on you (whether by court order, + agreement or otherwise) that contradict the conditions of this + License, they do not excuse you from the conditions of this + License. If you cannot distribute so as to satisfy simultaneously + your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the + Program at all. For example, if a patent license would not permit + royalty-free redistribution of the Program by all those who + receive copies directly or indirectly through you, then the only + way you could satisfy both it and this License would be to refrain + entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of + any such claims; this section has the sole purpose of protecting + the integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this + License incorporates the limitation as if written in the body of + this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such + new versions will be similar in spirit to the present version, but + may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies + to it and "any later version", you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Program + does not specify a version number of this License, you may choose + any version ever published by the Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted + by the Free Software Foundation, write to the Free Software + Foundation; we sometimes make exceptions for this. Our decision + will be guided by the two goals of preserving the free status of + all derivatives of our free software and of promoting the sharing + and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE + LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE + QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY + SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY + MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, + INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU + OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY + OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs +============================================= + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YYYY NAME OF AUTHOR + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + SIGNATURE OF TY COON, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, +you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Library General Public License instead of this License. diff --git a/Source/Modulos/Banca electronica/Utiles/SEPAUnit/license.txt b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/license.txt new file mode 100644 index 0000000..142b8dd --- /dev/null +++ b/Source/Modulos/Banca electronica/Utiles/SEPAUnit/license.txt @@ -0,0 +1,3 @@ +The license under which this software is released is the GPLv2 (or +later) from the Free Software Foundation. A copy of the GPLv2 license +is included, see "gpl.txt". \ No newline at end of file diff --git a/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dpk b/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dpk index 9a48a0c..87abb27 100644 --- a/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dpk +++ b/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dpk @@ -53,6 +53,7 @@ contains uBancaElectronicaViewRegister in 'uBancaElectronicaViewRegister.pas', uEditorExportacionNorma19 in 'uEditorExportacionNorma19.pas' {fEditorExportacionNorma19}, uEditorExportacionNorma19SEPA in 'uEditorExportacionNorma19SEPA.pas' {fEditorExportacionNorma19SEPA}, - uEditorExportacionNorma32 in 'uEditorExportacionNorma32.pas' {fEditorExportacionNorma32}; + uEditorExportacionNorma32 in 'uEditorExportacionNorma32.pas' {fEditorExportacionNorma32}, + uEditorExportacionNorma19SEPAXML in 'uEditorExportacionNorma19SEPAXML.pas' {fEditorExportacionNorma19SEPAXML}; end. diff --git a/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dproj b/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dproj index a24f16b..9ddcbd6 100644 --- a/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dproj +++ b/Source/Modulos/Banca electronica/Views/BancaElectronica_view.dproj @@ -47,29 +47,25 @@ MainSource - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
fEditorExportacionNorma19
@@ -77,9 +73,16 @@
fEditorExportacionNorma19SEPA
+ +
fEditorExportacionNorma19SEPAXM
+
fEditorExportacionNorma32
+ + + +