{"id":119,"date":"2021-10-26T10:49:42","date_gmt":"2021-10-26T16:49:42","guid":{"rendered":"https:\/\/fbedolla.com\/?p=119"},"modified":"2021-10-26T11:16:12","modified_gmt":"2021-10-26T17:16:12","slug":"a-new-old-app-idea-bank-layouts","status":"publish","type":"post","link":"https:\/\/fbedolla.com\/index.php\/2021\/10\/26\/a-new-old-app-idea-bank-layouts\/","title":{"rendered":"A new (old) app idea, bank layouts"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"996\" height=\"625\" src=\"https:\/\/fbedolla.com\/wp-content\/uploads\/2021\/10\/banktransfers.jpg\" alt=\"\" class=\"wp-image-121\" srcset=\"https:\/\/fbedolla.com\/wp-content\/uploads\/2021\/10\/banktransfers.jpg 996w, https:\/\/fbedolla.com\/wp-content\/uploads\/2021\/10\/banktransfers-300x188.jpg 300w, https:\/\/fbedolla.com\/wp-content\/uploads\/2021\/10\/banktransfers-768x482.jpg 768w, https:\/\/fbedolla.com\/wp-content\/uploads\/2021\/10\/banktransfers-816x512.jpg 816w\" sizes=\"auto, (max-width: 996px) 100vw, 996px\" \/><\/figure>\n\n\n\n<p>This time I want to write about a problem that affects every Latam implementation, the bank payments.<\/p>\n\n\n\n<p>Unlike Europe and countries with more organized banking systems, in Latam we have a chaotic bank system in which every bank creates and use their own \u201cschema\u201d to accept the payment transactions.<\/p>\n\n\n\n<p>Some bank even has multiple format definitions based in the operation type, vendor payment, payroll payment, other bank payment, and others.<\/p>\n\n\n\n<p>I saw some \u201cpayment solutions\u201d in the appsource, I don\u2019t know how much cost those apps but is very difficult to understand why we don\u2019t have similar solutions from Latam partners.<\/p>\n\n\n\n<p>I believe that Latam partners work with banks, I mean, they have bank accounts and know someone in the bank, maybe the people which manages their accounts, so, why don\u2019t ask that person for the bank layouts, and develop an extension for that?<\/p>\n\n\n\n<p>Yes, I know about the Host2Host service but you can use that service or upload a txt file to the bank site.<\/p>\n\n\n\n<p>I\u2019m going to focus on the txt file this time.<\/p>\n\n\n\n<p>First, you need to decide if you want only one codeunit or one per format or bank, this time I chose only one codeunit to rule them all layouts.<\/p>\n\n\n\n<p>I created a &#8220;base payment table&#8221; to put the information there in the first place and then start witht he txt file. This allows me to grow the solution and add more fields to add more banks and avoid to add fields in the General Journal Line table keeping that table clean.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n\/\/\/ Table ExportPayment (ID 58100).\n\/\/\/ &lt;\/summary&gt;\ntable 58100 ExportPayment\n{\n    Caption = 'ExportPayment';\n    DataClassification = CustomerContent;\n\n    fields\n    {\n        field(1; \"Line No\"; Integer)\n        {\n            Caption = 'Line No';\n            DataClassification = CustomerContent;\n        }\n        field(2; \"Origin Bank\"; Code&#91;20])\n        {\n            Caption = 'Origin Bank';\n            DataClassification = CustomerContent;\n        }\n        field(3; \"Origin Account No\"; Text&#91;30])\n        {\n            Caption = 'Origin Account No';\n            DataClassification = CustomerContent;\n        }\n        field(4; \"Origin Branch No\"; Text&#91;20])\n        {\n            Caption = 'Origin Branch No';\n            DataClassification = CustomerContent;\n        }\n        field(5; \"Origin Bank Place\"; Text&#91;20])\n        {\n            Caption = 'Origin Bank Place';\n            DataClassification = CustomerContent;\n        }\n        field(7; \"Origin Bank Currency\"; Code&#91;10])\n        {\n            Caption = 'Origin Bank Currency';\n            DataClassification = CustomerContent;\n        }\n        field(8; \"Origin Bank Country\"; Code&#91;10])\n        {\n            Caption = 'Origin Bank Country';\n            DataClassification = CustomerContent;\n        }\n        field(9; \"Origin Bank Export Code\"; Enum CCExpBankCodes)\n        {\n            Caption = 'Origin Bank Export Code';\n            DataClassification = CustomerContent;\n        }\n        field(10; \"Bank Agreement\"; Code&#91;9])\n        {\n            Caption = 'Bank Agreement';\n            DataClassification = CustomerContent;\n        }\n        field(11;\"Payment Reference\"; Text&#91;30])\n        {\n            Caption = 'Payment Reference';\n            DataClassification = CustomerContent;\n        }\n        field(12; Description; Text&#91;50])\n        {\n            Caption = 'Description';\n            DataClassification = CustomerContent;\n        }\n        field(20; \"Vendor No\"; Code&#91;20])\n        {\n            Caption = 'Vendor No';\n            DataClassification = CustomerContent;\n        }\n        field(21; \"Vendor ID \"; Code&#91;20])\n        {\n            Caption = 'Vendor ID ';\n            DataClassification = CustomerContent;\n        }\n        field(22; \"Invoice to Pay\"; Code&#91;20])\n        {\n            Caption = 'Invoice to Pay';\n            DataClassification = CustomerContent;\n        }\n        field(23; \"Vendor Bank\"; Code&#91;20])\n        {\n            Caption = 'Vendor Bank';\n            DataClassification = CustomerContent;\n        }\n        field(24; \"Vendor Bank Account No\"; Text&#91;30])\n        {\n            Caption = 'Vendor Bank Account No';\n            DataClassification = CustomerContent;\n        }\n        field(25; \"Destination Bank Branch\"; Text&#91;20])\n        {\n            Caption = 'Destination Bank Branch';\n            DataClassification = CustomerContent;\n        }\n        field(26; \"Destination Bank Place\"; Text&#91;20])\n        {\n            Caption = 'Destination Bank Place';\n            DataClassification = CustomerContent;\n        }\n        field(27; \"Payment Currency Code\"; Code&#91;10])\n        {\n            Caption = 'Payment Currency Code';\n            DataClassification = CustomerContent;\n        }\n        field(28; \"Destination Bank Country\"; Code&#91;10])\n        {\n            Caption = 'Destination Bank Country';\n            DataClassification = CustomerContent;\n        }\n        field(29; \"Destination Bank Export Code\"; Enum CCExpBankCodes)\n        {\n            Caption = 'Destination Bank Export Code';\n            DataClassification = CustomerContent;\n        }\n        field(30; \"Payment Amount\"; Decimal)\n        {\n            Caption = 'Payment Amount';\n            DataClassification = CustomerContent;\n        }\n        field(36;\"Vendor Name\";Text&#91;50])\n        {\n            Caption = 'Vendor Name';\n            DataClassification = CustomerContent;\n        }\n        field(40; BBVAOperType; Text&#91;1])\n        {\n            Caption = 'BBVAOperType';\n            DataClassification = CustomerContent;\n        }\n        field(41; BBVARefNo; Text&#91;25])\n        {\n            Caption = 'BBVARefNo';\n            DataClassification = CustomerContent;\n        }\n        field(42; BBVAAccType; Text&#91;2])\n        {\n            Caption = 'BBVAAccType';\n            DataClassification = CustomerContent;\n        }\n        field(60; AreSameBank; Boolean)\n        {\n            Caption = 'AreSameBank';\n            DataClassification = CustomerContent;\n        }\n        field(61; AreSameCurrency; Boolean)\n        {\n            Caption = 'AreSameCurrency';\n            DataClassification = CustomerContent;\n        }\n        field(62; AreSameCountry; Boolean)\n        {\n            Caption = 'AreSameCountry';\n            DataClassification = CustomerContent;\n        }\n        field(100; \"Exported to Payment File\"; Boolean)\n        {\n            Caption ='Exported to Payment File';\n            DataClassification = CustomerContent;\n        }\n    }\n    keys\n    {\n        key(PK; \"Line No\")\n        {\n            Clustered = true;\n        }\n    }\n\n}<\/code><\/pre>\n\n\n\n<p>I call everything from the payment journal so my first procedure to call in every export is the next code and then, create the txt file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n    \/\/\/ PrepareExport.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=\"JTN\"&gt;Code&#91;10].&lt;\/param&gt;\n    \/\/\/ &lt;param name=\"JBN\"&gt;Code&#91;10].&lt;\/param&gt;\n    procedure PrepareExport(JTN: Code&#91;10]; JBN: Code&#91;10])\n    var\n        ExpData: Record ExportPayment;\n        GenJnlLine: Record \"Gen. Journal Line\";\n    begin\n        ExpData.Reset();\n        if ExpData.FindSet() then\n            ExpData.DeleteAll();\n\n        GenJnlLine.Reset();\n        GenJnlLine.SetRange(\"Journal Template Name\", JTN);\n        GenJnlLine.SetRange(\"Journal Batch Name\", JBN);\n        GenJnlLine.SetRange(\"Exported to Payment File\", false);\n        if GenJnlLine.FindSet() then\n            repeat\n                ExpData.\"Line No\" := GenJnlLine.\"Line No.\";\n                ExpData.\"Origin Bank\" := GenJnlLine.\"Bal. Account No.\";\n                ExpData.\"Origin Account No\" := GetBankAccNo(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Origin Branch No\" := GetBankBranch(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Origin Bank Place\" := GetBankPlace(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Origin Bank Currency\" := GetBankCurr(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Origin Bank Country\" := GetBankCountry(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Origin Bank Export Code\" := GetBankExpCode(GenJnlLine.\"Bal. Account No.\");\n                ExpData.Description := GenJnlLine.Description;\n                ExpData.\"Bank Agreement\" := GetBankAgr(GenJnlLine.\"Bal. Account No.\");\n                ExpData.\"Vendor No\" := GenJnlLine.\"Account No.\";\n                ExpData.\"Vendor Name\" := GetVendorName(GenJnlLine.\"Account No.\");\n                ExpData.\"Vendor ID \" := GetVendorID(GenJnlLine.\"Account No.\");\n                ExpData.\"Invoice to Pay\" := GenJnlLine.\"Applies-to Doc. No.\";\n                ExpData.\"Vendor Bank\" := GenJnlLine.\"Recipient Bank Account\";\n                ExpData.\"Vendor Bank Account No\" := GetVendBankAcc(GenJnlLine.\"Account No.\", GenJnlLine.\"Recipient Bank Account\");\n                ExpData.\"Destination Bank Branch\" := '';\n                ExpData.\"Destination Bank Place\" := '';\n                ExpData.\"Destination Bank Country\" := GetVendBankCountry(GenJnlLine.\"Account No.\", GenJnlLine.\"Recipient Bank Account\");\n                ExpData.\"Destination Bank Export Code\" := GetVendBankExpCode(GenJnlLine.\"Account No.\", GenJnlLine.\"Recipient Bank Account\");\n                if GenJnlLine.\"Currency Code\" &lt;&gt; '' then\n                    ExpData.\"Payment Currency Code\" := GenJnlLine.\"Currency Code\"\n                else\n                    ExpData.\"Payment Currency Code\" := 'MXN';\n                ExpData.\"Payment Amount\" := GenJnlLine.Amount;\n\n                \/\/Here starts a new section to define some options for each bank in the codeunit\n                if ExpData.\"Origin Bank Export Code\" = ExpData.\"Destination Bank Export Code\" then\n                    ExpData.AreSameBank := true\n                else\n                    ExpData.AreSameBank := false;\n\n                if ExpData.\"Origin Bank Country\" = ExpData.\"Destination Bank Country\" then\n                    ExpData.AreSameCountry := true\n                else\n                    ExpData.AreSameCountry := false;\n                if ExpData.\"Origin Bank Currency\" = ExpData.\"Payment Currency Code\" then\n                    ExpData.AreSameCurrency := true\n                else\n                    ExpData.AreSameCurrency := false;\n\n                if ExpData.AreSameCountry = true then\n                    ExpData.BBVAOperType := '2'\n                else\n                    ExpData.BBVAOperType := '4';\n\n                if (ExpData.AreSameCurrency = true) and (ExpData.AreSameBank = true) then\n                    ExpData.BBVAOperType := '2'\n                else\n                    ExpData.BBVAOperType := '6';\n\n                ExpData.Insert(true);\n\n            until GenJnlLine.Next() = 0;\n    end;<\/code><\/pre>\n\n\n\n<p>Let\u2019s look one of the most used banks in Mexico, BBVA.<\/p>\n\n\n\n<p>They have a 1,366 positions layout, this layout has a 2 sections, header, and detail. The detail sections contain 106 fields that sums those 1366 positions and covers almost any BBVA supported transaction.<\/p>\n\n\n\n<p>This code contains all fields for bbva layout<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/\/\/ &lt;summary&gt;\n    \/\/\/ CreateLayout1.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=\"JTN\"&gt;Code&#91;10].&lt;\/param&gt;\n    \/\/\/ &lt;param name=\"JBN\"&gt;Code&#91;10].&lt;\/param&gt;\n    procedure CreateBBVA(JTN: Code&#91;10]; JBN: Code&#91;10])\n    var\n        InStr: InStream;\n        OutStr: OutStream;\n        tmpblob: Codeunit \"Temp Blob\";\n        FileName: Text;\n        CRLF: Text&#91;2];\n        SpaceStr: Text;\n        ZeroStr: Text;\n        TotalAmnt: Decimal;\n        ExpPaym: Record ExportPayment;\n\n    begin\n        CRLF&#91;1] := 13;\n        CRLF&#91;2] := 10;\n        FileName := 'BBVA.txt';\n        SpaceStr := ' ';\n        TotalAmnt := 0;\n\n        ExpPaym.Reset();\n        ExpPaym.SetRange(\"Exported to Payment File\", false);\n        if ExpPaym.FindSet() then begin\n            tmpBlob.CreateOutStream(OutStr, TextEncoding::Windows);\n            OutStr.WriteText(\n            \/\/&gt;&gt; Start Header\/Inicia Header\n            'H' + \/\/1 Record type\/Indicador del registro\n            Format(ExpPaym.\"Bank Agreement\").PadLeft(9, '0') + \/\/2 Arrangement\/Convenio\n            Format(WorkDate(), 0, 9) + \/\/3 Send Date\/Fecha de envio\n            '01' + \/\/4 Recipient Type\/Tipo de validaci\u00f3n del tercero\n            PadStr('PAGO' + Format(WorkDate, 0, '&lt;Year4&gt;&lt;Month,2&gt;&lt;Day,2&gt;'), 30, ' ') + \/\/5 file name\/Clave del archivo\n            '00' + \/\/6 Response Code\/C\u00f3digo de respuesta\n            PadStr(SpaceStr, 20, ' ') + \/\/7 Response Description\/Descripci\u00f3n c\u00f3digo de respuesta\n            PadStr(SpaceStr, 3, ' ') + \/\/8 Channel\/Canal\n            PadStr(SpaceStr, 35, ' ') + \/\/9 CHarge Account\/Cuenta de cargo\n            PadStr(SpaceStr, 3, ' ') +\/\/10 Arrangement Currency\/Divisa del convenio\n            PadStr(SpaceStr, 1251, ' ') +\/\/11 Filler 1251 spaces\/espacios\n            CRLF\n            );\n            \/\/&lt;&lt;End Header\/termina header\n            repeat\n                OutStr.WriteText(\n                \/\/&gt;&gt;Start Detail\/Inicia Detalle \n                'D' + \/\/1 Record number\/Indicador del registtro\n                'A' + \/\/2 Instruction\/Instrucci\u00f3n\n                'P' + \/\/3 Document Type\/Tipo de documento\n                PadStr(ExpPaym.\"Invoice to Pay\", 20, ' ') + \/\/4 Reference\/Referencia SIT\n                PadStr(ExpPaym.\"Vendor No\", 30, ' ') + \/\/5 Vendor No, add empty spaces\/Clave de proveedor o concepto o datos RSTM TODO, revisar el largo de la cuenta proveedor y sumarle a 30 padstr\n                'PDA' + \/\/6 Service Type\/Tipo de servicio\n                ExpPaym.BBVAOperType + \/\/7 Operation Code\/C\u00f3digo de operaci\u00f3n\n                PadStr(ZeroStr, 20, ' ') + \/\/8 Charge Account and vendor No for SPID\/Cuenta de cargo y RFC del proveedor para SPID\n                PadStr(SpaceStr, 15, ' ') + \/\/9 Filler\n                PadStr(SpaceStr, 25, ' ') + \/\/10 Numerical reference\/Referencia Num\u00e9rica o Leyenda personalizada de CARGO\/Concepto o Codigo de seguridad y folio identificador RSTM\n                PadStr('PAGO' + Format(ExpPaym.\"Invoice to Pay\"), 37, ' ') + \/\/11 Pay Reason\/Motivo de pago o Leyenda personalizada de CARGO\/ Referencia Amplia TODO, revisar el largo de la cuenta proveedor y sumarle a 30 padstr\n                PadStr(SpaceStr, 15, ' ') + \/\/12 Filler\n                PadStr(ExpPaym.\"Payment Reference\", 25, ' ') + \/\/13 Payment Description\/Leyenda personalizada de ABONO\/CONCEPTO\n                PadStr(ExpPaym.\"Payment Reference\", 37, ' ') + \/\/14 CIE Concept\/Concepto CIE O Leyenda personalizada de ABONO Referencia Amplia\n                'N' + \/\/15 Fiscal Receipt\/Comprobante fiscal\n                PadStr(SpaceStr, 8, ' ') + \/\/16 Filler\n                '40' +\/\/17 Account Type\/Tipo de cuenta\n                PadStr(SpaceStr, 35, ' ') + \/\/18 Credit Account\/Cuenta de abono\n                PadStr(SpaceStr, 40, ' ') + \/\/19 Receipt Name\/Nombre del 1er Beneficiario o Nombre del titular de la cuenta de abono\n                PadStr(SpaceStr, 1, ' ') + \/\/20 Receipt ID Code\/Clave de identificaci\u00f3n del 1er Beneficiario\n                PadStr(SpaceStr, 30, ' ') + \/\/21 Receipt ID Number\/N\u00famero identificaci\u00f3n 1er Beneficiario\n                PadStr(SpaceStr, 40, ' ') + \/\/22 Receipt Name\/Nombre del 2do Beneficiario o Nombre comercial de la empresa\n                PadStr(SpaceStr, 1, ' ') + \/\/23 2nd Receipt ID Code\/Clave de identificaci\u00f3n del 2do Beneficiario\n                PadStr(SpaceStr, 30, ' ') + \/\/24 2nd Receipt ID Number\/N\u00famero identificaci\u00f3n 2do Beneficiario o CURP del Beneficiario para RSTM O Clave de rastreo para interbanciarios\n                ExpPaym.\"Payment Currency Code\" + \/\/25 Destination transfer currency\/Divisa de la transferencia destino\n                PadStr(SpaceStr, 11, ' ') + \/\/26 BIC CODE\/CLAVE BIC\n                PadStr(SpaceStr, 9, ' ') + \/\/27 ABA CODE\/CLAVE ABA\n                'FA' + \/\/28 Document Code\/Clave de documento\n                Format(ExpPaym.\"Payment Amount\" * 100, 0, 2).PadLeft(15, '0') + \/\/29 Payment Amount\/Importe del documento\n                PadStr(ZeroStr, 15, '0') + \/\/30 Filler\n                '01' + \/\/31 Confirmation Type\/Tipo de confirmaci\u00f3n\n                PadStr(SpaceStr, 50, ' ') + \/\/32 Email or celullar\n                'N' + \/\/33 Interest frequency\/Periodicidad de interes\n                PadStr(ZeroStr, 8, '0') + \/\/34 Filler N\u00fam (2.6)\n                PadStr(ZeroStr, 4, '0') + \/\/35 Filler N\u00fam (2.2)\n                Format(WorkDate(), 0, 9) + \/\/36 Payment Date\/Fecha de pago\n                '0001-01-01' + \/\/37 Effective date\/Fecha de vigencia\n                '0001-01-01' + \/\/38 Grace date\/Fecha de gracia\n                '0001-01-01' + \/\/39 Effective date\/Fecha de vigencia\n                Format(WorkDate(), 0, 9) + \/\/40 Document Date\/Fecha del documento\n                'N' + \/\/41 Periodic Payment Indicator\/Indicador del pago recurrente\n                PadStr(SpaceStr, 1, ' ') + \/\/42 Filler\n                '0001-01-01' + \/\/43\n                '700' + \/\/44 Payment Detail\/Longitud de Datos adicionales o Detalle de pago\n                PadStr(SpaceStr, 700, ' ') + \/\/45 Additional Data\/Datos adicionales\n                PadStr(SpaceStr, 10, ' ') + \/\/46 Filler\n                PadStr(SpaceStr, 10, ' ') + \/\/47 Filler\n                PadStr(SpaceStr, 2, ' ') + \/\/48 Document Status Code\/C\u00f3digo de estatus del documento\n                PadStr(SpaceStr, 30, ' ') + \/\/49 Description of the document status code\/Descripci\u00f3n del c\u00f3digo estatus del documento\n                '0001-01-01' + \/\/50 Date of last document event\/Fecha de ultimo evento del documento\n                CRLF\n                );\n                TotalAmnt += ExpPaym.\"Payment Amount\";\n            until ExpPaym.Next() = 0;\n            \/\/&lt;&lt;End Detail\/Termina Detalle\n            \/\/&gt;&gt;Start summary\/Inicia Sumario\n            OutStr.WriteText(\n            'T' + \/\/1 REcord Indicator\/Indicador del registro\n            '' + \/\/2 Number of records High MXP (Mexican peso) Number of providers to pay are newrecords validate if payments can be summarized by provider and not n payments for n invoices\/N\u00famero de registros Altas MXP (peso mexicano) Numero de proveedores a pagar son altas validar si se pueden sumarizar los pagos por proveedor y no n pagos por n facturas\n            Format(TotalAmnt, 0, 2).PadLeft(15, '0') + \/\/3 Total amount newrecords MXP sum of invoice payments by supplier\/Importe total Altas MXP suma de pagos de facturas por proveedor\n            PadStr(ZeroStr, 10, '0') + \/\/4 Number of records Deletions MXP 10 zeros because there are no withdrawals is the registration file (Payments)\/N\u00famero de registros Bajas MXP 10 ceros por que no hay bajas es archivo de altas (Pagos)\n            PadStr(ZeroStr, 215, '0') + \/\/5 al 21\n            '' + \/\/22 Number of new records USD (American dollar) how many payments will normally be paid per provider USD or 10 zeros\/N\u00famero de registros ALTAS USD (d\u00f3lar americano) cuantos pagos se haran normalmente se paga por proveedor USD o 10 ceros\n            '' + \/\/23 Total Amount new records USD sum of invoice payments per supplier USD or 15 zerosImportte Total Altas USD suma de pagos de facturas por proveedor USD o 15 ceros\n            PadStr(ZeroStr, 125, '0') + \/\/24 al 33\n            '' + \/\/34 Registration number new records EUR how many payments will normally be paid per provider EUR or 10 zerosN\u00famero de registro Altas EUR cuantos pagos se haran normalmente se paga por proveedor EUR o 10 ceros\n            '' + \/\/35 New Records Total Amount EUR\/Importe total Altas EUR\n            PadStr(ZeroStr, 125, '0') + \/\/36 al 45\n            '' + \/\/46 New Records Count CAD\/N\u00famero de registros Altas CAD\n            '' + \/\/47 New Records Total Amount CAD\/Importe total Altas CAD\n            PadStr(ZeroStr, 125, '0') + \/\/48 al 57\n            '' + \/\/58 New Records Count CHF\/N\u00famero de registros Altas CHF\n            '' + \/\/59 New Records Total Amount CHF\/Importe total Altas CHF\n            PadStr(ZeroStr, 125, '0') + \/\/60 al 69\n            '' + \/\/70 New Records Count GBP\/N\u00famero de registros Altas GBP\n            '' + \/\/71 New Records Total Amount GBP\/Importe total Altas GBP\n            PadStr(ZeroStr, 125, '0') + \/\/72 al 81\n            '' + \/\/82 New Records Count SEK\/N\u00famero de registros Altas SEK\n            '' + \/\/83 New Records Total Amount SEK\/Importe total Altas SEK\n            PadStr(ZeroStr, 125, '0') + \/\/84 al 93\n            '' + \/\/94 New Records Count JPY\/N\u00famero de registros Altas JPY\n            '' + \/\/95 New Records Total Amount JPY\/Importe total Altas JPY\n            PadStr(ZeroStr, 190, '0') + \/\/96 al 106\n            \/\/&lt;&lt;Termina Sumario\n            CRLF\n            );\n            tmpBlob.CreateInStream(InStr, TextEncoding::Windows);\n            DownloadFromStream(InStr, '', '', '', FileName);\n        end;\n    end;<\/code><\/pre>\n\n\n\n<p>when you check the code, you will find references to journal and new table fields, also, you can add code to use more currencies in the summary. Text dates are as BBVA ask it.<\/p>\n\n\n\n<p>Now, let&#8217;s check a small layout, this is Banorte and has fewer fields <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n    \/\/\/ CreateBNTE.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=\"JTN\"&gt;Code&#91;10].&lt;\/param&gt;\n    \/\/\/ &lt;param name=\"JBN\"&gt;Code&#91;10].&lt;\/param&gt;\n    procedure CreateBNTE(JTN: Code&#91;10]; JBN: Code&#91;10])\n    var\n        InStr: InStream;\n        OutStr: OutStream;\n        tmpblob1: Codeunit \"Temp Blob\";\n        FileName: Text;\n        CRLF: Text&#91;2];\n        SpaceStr: Text;\n        ZeroStr: Text;\n        TotalAmnt: Decimal;\n        ExpPaym: Record ExportPayment;\n    begin\n        CRLF&#91;1] := 13;\n        CRLF&#91;2] := 10;\n        FileName := 'BNTE.txt';\n        SpaceStr := ' ';\n        TotalAmnt := 0;\n\n        ExpPaym.Reset();\n        ExpPaym.SetRange(\"Exported to Payment File\", false);\n        if ExpPaym.FindSet() then begin\n            tmpBlob1.CreateOutStream(OutStr, TextEncoding::Windows);\n            repeat\n                OutStr.WriteText(\n                '07' + \/\/1 OPI Operation\/Operaci\u00f3n OPIs\n                PadStr(ExpPaym.\"Vendor No\", 13, ' ') + \/\/2 ID Code\/Clave ID\n                PadStr(SpaceStr, 10, ' ') + \/\/3 Origin Account\/Cuenta Origen\n                PadStr(SpaceStr, 20, ' ') + \/\/4 Destination Account CLABE\/Cuenta\/CLABE Destino\n                Format(ExpPaym.\"Payment Amount\", 0, 2).PadLeft(16,'0') + \/\/5 Amount\/Importe\n                Format(ExpPaym.\"Payment Reference\").PadLeft(7,'0') + \/\/6 Reference\/Referencia\n                PadStr(ExpPaym.Description, 30, ' ') + \/\/7 Description\/Descripci\u00f3n\n                PadStr(GetCompRFC, 13, ' ') + \/\/8 Paying TAX ID\/RFC Ordenante\n                Format((ExpPaym.\"Payment Amount\"-(ExpPaym.\"Payment Amount\"\/1.16)),0,2).PadLeft(14,'0') + \/\/9 TAX(VAT)\/IVA\n                Format(WorkDate, 0, '&lt;Day,2&gt;&lt;Month,2&gt;&lt;Year4&gt;') + \/\/10 Apply on Date\/Fecha aplicaci\u00f3n\n                'X' + \/\/11 Payment Instruction\/Instrucci\u00f3n de pago\n                CRLF\n                );\n            until ExpPaym.Next() = 0;\n        end;\n        tmpBlob1.CreateInStream(InStr, TextEncoding::Windows);\n        DownloadFromStream(InStr, '', '', '', FileName);\n    end;<\/code><\/pre>\n\n\n\n<p>As you can see, I\u00b4m using the same source table, so if I need to add more fields because I add a new bank layout, I just simply add the required fields without touch the existing layouts.<\/p>\n\n\n\n<p>Finally, I added a last bank layout, this time Santander<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n    \/\/\/ CreateSANT.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=\"JTN\"&gt;Code&#91;10].&lt;\/param&gt;\n    \/\/\/ &lt;param name=\"JBN\"&gt;Code&#91;10].&lt;\/param&gt;\n    procedure CreateSANT(JTN: Code&#91;10]; JBN: Code&#91;10])\n    var\n        InStr: InStream;\n        OutStr: OutStream;\n        tmpblob2: Codeunit \"Temp Blob\";\n        FileName: Text;\n        CRLF: Text&#91;2];\n        SpaceStr: Text;\n        ZeroStr: Text;\n        TotalAmnt: Decimal;\n        ExpPaym: Record ExportPayment;\n    begin\n        CRLF&#91;1] := 13;\n        CRLF&#91;2] := 10;\n        FileName := 'SANT.txt';\n        SpaceStr := ' ';\n        TotalAmnt := 0;\n\n        ExpPaym.Reset();\n        ExpPaym.SetRange(\"Exported to Payment File\", false);\n        if ExpPaym.FindSet() then begin\n            tmpBlob2.CreateOutStream(OutStr, TextEncoding::Windows);\n            repeat\n                OutStr.WriteText(\n                PadStr(ExpPaym.\"Origin Account No\", 16, ' ') + \/\/1 Charged account\/Cuenta de Cargo\n                PadStr(ExpPaym.\"Vendor Bank Account No\", 20, ' ') + \/\/2 Crediot Account\/Cuenta de abono \/ N\u00famero M\u00f3vil\n                PadStr(SpaceStr, 5, ' ') + \/\/3 Bank\/Banco\n                PadStr(ExpPaym.\"Vendor Name\", 40, ' ') + \/\/4 Receipt\/Beneficiario\n                PadStr(SpaceStr, 4, ' ') + \/\/5 Branch\/Sucursal\n                Format(ExpPaym.\"Payment Amount\", 0, 2).PadLeft(16,'0')+ \/\/6 Amount\/Importe\n                PadStr(SpaceStr, 7, ' ') + \/\/7 City\/Plaza\n                PadStr(ExpPaym.Description, 40, ' ') + \/\/8 Concept\/Concepto\n                PadStr(SpaceStr, 90, ' ') + \/\/9 Blank Space\/Espacio en Blanco\n                PadStr(SpaceStr, 1, ' ') + \/\/10 Fiscal Accoutn Statement\/Estado de cuenta fiscal\n                PadStr(SpaceStr, 13, ' ') + \/\/11 TAX ID\/RFC\n                PadStr(ZeroStr, 15, '0') + \/\/12 TAX(VAT)\/IVA\n                PadStr(ExpPaym.\"Payment Reference\", 7, ' ') + \/\/13 Originator Reference\/Referencia Ordenante\n                PadStr(SpaceStr, 1, ' ') + \/\/14 Application Form\/Forma de aplicaci\u00f3n\n                PadStr(SpaceStr, 2, ' ') + \/\/15 Payment Type\/Tipo de Pago\n                PadStr(SpaceStr, 1, ' ') + \/\/16 Application Date\/Fecha de aplicaci\u00f3n\n                CRLF\n                );\n            until ExpPaym.Next() = 0;\n        end;\n        tmpBlob2.CreateInStream(InStr, TextEncoding::Windows);\n        DownloadFromStream(InStr, '', '', '', FileName);\n    end;<\/code><\/pre>\n\n\n\n<p>And some procedures to get general information for every layout<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local procedure GetCompRFC(): Text\n    var\n        CompInfo: Record \"Company Information\";\n    begin\n        CompInfo.Get();\n        exit(CompInfo.\"RFC No.\")\n    end;\n\n    local procedure GetBankAccNo(BankNo: Code&#91;20]): Text&#91;30]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Bank Account No.\")\n    end;\n\n    local procedure GetBankBranch(BankNo: Code&#91;20]): Text&#91;30]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Bank Branch No.\")\n    end;\n\n    local procedure GetBankPlace(BankNo: Code&#91;20]): Text&#91;30]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Bank Account No.\")\n    end;\n\n    local procedure GetBankAgr(BankNo: Code&#91;20]): Text&#91;30]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Bank Agreement\")\n    end;\n\n    local procedure GetBankCurr(BankNo: Code&#91;20]): Text&#91;10]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            if banks.\"Currency Code\" &lt;&gt; '' then\n                exit(Banks.\"Currency Code\")\n            else\n                exit('MXN');\n    end;\n\n    local procedure GetBankCountry(BankNo: Code&#91;20]): Text&#91;10]\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Country\/Region Code\")\n    end;\n\n    local procedure GetBankExpCode(BankNo: Code&#91;20]): Enum CCExpBankCodes\n    var\n        Banks: Record \"Bank Account\";\n    begin\n        Banks.Reset();\n        Banks.SetRange(\"No.\", BankNo);\n        if Banks.findset then\n            exit(Banks.\"Bank Export Code\");\n    end;\n\n    local procedure GetVendorID(VendNo: Code&#91;20]): Code&#91;20]\n    var\n        Vend: Record Vendor;\n    begin\n        Vend.Reset();\n        Vend.SetRange(\"No.\", VendNo);\n        if Vend.FindSet() then\n            exit(Vend.\"RFC No.\");\n    end;\n    local procedure GetVendorName(VendNo: Code&#91;20]): Text&#91;50]\n    var\n        Vend: Record Vendor;\n    begin\n        Vend.Reset();\n        Vend.SetRange(\"No.\", VendNo);\n        if Vend.FindSet() then\n            exit(Vend.Name);\n    end;\n\n    local procedure GetVendBankAcc(VendNo: Code&#91;20]; Vendbank: Code&#91;20]): Code&#91;20]\n    var\n        VeBank: Record \"Vendor Bank Account\";\n    begin\n        VeBank.Reset();\n        VeBank.SetRange(\"Vendor No.\", VendNo);\n        VeBank.SetRange(Code, Vendbank);\n        if VeBank.FindSet() then\n            exit(VeBank.\"Bank Account No.\");\n    end;\n\n    local procedure GetVendBankCountry(VendNo: Code&#91;20]; Vendbank: Code&#91;20]): Code&#91;20]\n    var\n        VeBank: Record \"Vendor Bank Account\";\n    begin\n        VeBank.Reset();\n        VeBank.SetRange(\"Vendor No.\", VendNo);\n        VeBank.SetRange(Code, Vendbank);\n        if VeBank.FindSet() then\n            exit(VeBank.\"Country\/Region Code\");\n    end;\n\n    local procedure GetVendBankExpCode(VendNo: Code&#91;20]; Vendbank: Code&#91;20]): Enum ExpBankCodes\n    var\n        VeBank: Record \"Vendor Bank Account\";\n    begin\n        VeBank.Reset();\n        VeBank.SetRange(\"Vendor No.\", VendNo);\n        VeBank.SetRange(Code, Vendbank);\n        if VeBank.FindSet() then\n            exit(VeBank.\"Bank Export Code\");\n    end;<\/code><\/pre>\n\n\n\n<p>So, lets talk about a new idea here:<\/p>\n\n\n\n<p>Lets make the base table available as a base required app, available with your first &#8220;layout purchase&#8221;. For example, the customer wants to purchase BBVA so, we sell BBVA layout plus base table, later, the same customer wants Banorte, so our Banorte app, checks if the base table exists and the fields, if detects that the base table needs an udpate, then apply the updated and add the new fields, if not change is need, just add the new layout codeunit and make required mods in some pages.  <\/p>\n\n\n\n<p>With this approach, we can build a multi layout solution that we can sell by parts and those apps relies in a &#8220;single source table&#8221; and sell this solution to any customer in Mexico, and maybe you can &#8220;clone&#8221; this approach to other countries.<\/p>\n\n\n\n<p>If you need to use Host to Host solutions or webservices , you simply add another layer to accomplish these throught powerapps or BC web services calls. <\/p>\n\n\n\n<p>Feel free to use and modify the code according to your needs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This time I want to write about a problem that affects every Latam implementation, the bank payments. Unlike Europe and countries with more organized banking systems, in Latam we have a chaotic bank system in which every bank creates and use their own \u201cschema\u201d to accept the payment transactions. Some bank even has multiple format [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4,7],"tags":[],"class_list":["post-119","post","type-post","status-publish","format-standard","hentry","category-coding","category-ideas"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":4,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":124,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/posts\/119\/revisions\/124"}],"wp:attachment":[{"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fbedolla.com\/index.php\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}