iso20022-codegen.rs (6745B)
1 /* 2 * This file is part of LibEuFin. 3 * Copyright (C) 2026 Taler Systems S.A. 4 5 * LibEuFin is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation; either version 3, or 8 * (at your option) any later version. 9 10 * LibEuFin is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General 13 * Public License for more details. 14 15 * You should have received a copy of the GNU Affero General Public 16 * License along with LibEuFin; see the file COPYING. If not, see 17 * <http://www.gnu.org/licenses/> 18 */ 19 20 use std::{ 21 collections::BTreeMap, 22 fmt::Write as _, 23 io::{Cursor, Read as _}, 24 }; 25 26 use calamine::{DataType, Reader as _, Xlsx}; 27 use reqwest::StatusCode; 28 use tokio::join; 29 use zip::ZipArchive; 30 31 pub async fn iso20022codegen_external_code_set() { 32 let res = reqwest::get( 33 "https://www.iso20022.org/sites/default/files/media/file/ExternalCodeSets_XLSX.zip", 34 ) 35 .await 36 .unwrap(); 37 38 assert_eq!(res.status(), StatusCode::OK); 39 let zipped = res.bytes().await.unwrap(); 40 let mut zip = ZipArchive::new(Cursor::new(&zipped)).unwrap(); 41 assert_eq!(zip.len(), 1); 42 43 let mut bytes = Vec::new(); 44 zip.by_index(0).unwrap().read_to_end(&mut bytes).unwrap(); 45 let mut excel: Xlsx<_> = calamine::open_workbook_from_rs(Cursor::new(&bytes)).unwrap(); 46 47 let mut code_sets: BTreeMap<_, Vec<_>> = BTreeMap::new(); 48 49 let range = excel.worksheet_range("AllCodeSets").unwrap(); 50 for row in range.rows() { 51 let set = row[0].as_string().unwrap(); 52 let code = row[1].as_string().unwrap(); 53 let name = row[2].as_string().unwrap().replace('-', ""); 54 let definition = row[3] 55 .as_string() 56 .unwrap() 57 .split(['.', '\n']) 58 .next() 59 .unwrap() 60 .trim() 61 .replace("_x000D_", ""); 62 let vec = code_sets.entry(set).or_default(); 63 vec.push((code, name, definition)) 64 } 65 66 let mut out = " 67 /* 68 * This file is part of LibEuFin. 69 * Copyright (C) 2026 Taler Systems S.A. 70 71 * LibEuFin is free software; you can redistribute it and/or modify 72 * it under the terms of the GNU Affero General Public License as 73 * published by the Free Software Foundation; either version 3, or 74 * (at your option) any later version. 75 76 * LibEuFin is distributed in the hope that it will be useful, but 77 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 78 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General 79 * Public License for more details. 80 81 * You should have received a copy of the GNU Affero General Public 82 * License along with LibEuFin; see the file COPYING. If not, see 83 * <http://www.gnu.org/licenses/> 84 */ 85 86 // THIS FILE IS GENERATED, DO NOT EDIT 87 88 use taler_macros::EnumMeta; 89 " 90 .to_string(); 91 92 for (set, enum_name) in [ 93 ("ExternalStatusReason1Code", "StatusReason"), 94 ("ExternalPaymentGroupStatus1Code", "PaymentGroupStatus"), 95 ( 96 "ExternalPaymentTransactionStatus1Code", 97 "PaymentTransactionStatus", 98 ), 99 ("ExternalReturnReason1Code", "ReturnReason"), 100 ] { 101 let set = code_sets.get_mut(set).unwrap(); 102 set.sort_unstable_by_key(|(code, _, _)| code.clone()); 103 writeln!( 104 &mut out, 105 " 106 #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumMeta)] 107 #[enum_meta(DomainCode, Description, Str)] 108 pub enum {enum_name} {{ 109 " 110 ) 111 .unwrap(); 112 for (code, name, description) in set.iter() { 113 writeln!(&mut out, "/// {description}").unwrap(); 114 writeln!(&mut out, "#[code = \"{code}\"]").unwrap(); 115 writeln!(&mut out, "{name},").unwrap(); 116 } 117 writeln!(&mut out, "}}").unwrap(); 118 } 119 std::fs::write("libeufin-ebics/src/iso20022/status_code.rs", out).unwrap(); 120 } 121 122 pub async fn iso20022codegen_bank_transaction_code() { 123 let res = reqwest::get( 124 "https://www.iso20022.org/sites/default/files/media/file/BTC_Codification_21March2024.xlsx", 125 ) 126 .await 127 .unwrap(); 128 129 assert_eq!(res.status(), StatusCode::OK); 130 let bytes = res.bytes().await.unwrap(); 131 let mut excel: Xlsx<_> = calamine::open_workbook_from_rs(Cursor::new(&bytes)).unwrap(); 132 133 let mut domain = BTreeMap::new(); 134 let mut family = BTreeMap::new(); 135 let mut subfamily = BTreeMap::new(); 136 137 let range = excel.worksheet_range("BTC_Codification").unwrap(); 138 139 for row in range.rows().skip(3) { 140 for (i, set) in [&mut domain, &mut family, &mut subfamily] 141 .into_iter() 142 .enumerate() 143 { 144 let name = row[i].as_string().unwrap(); 145 let code = row[i + 3].as_string().unwrap(); 146 let code = code.trim().to_string(); 147 set.insert(code, name); 148 } 149 } 150 151 let mut out = " 152 /* 153 * This file is part of LibEuFin. 154 * Copyright (C) 2026 Taler Systems S.A. 155 156 * LibEuFin is free software; you can redistribute it and/or modify 157 * it under the terms of the GNU Affero General Public License as 158 * published by the Free Software Foundation; either version 3, or 159 * (at your option) any later version. 160 161 * LibEuFin is distributed in the hope that it will be useful, but 162 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 163 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General 164 * Public License for more details. 165 166 * You should have received a copy of the GNU Affero General Public 167 * License along with LibEuFin; see the file COPYING. If not, see 168 * <http://www.gnu.org/licenses/> 169 */ 170 171 // THIS FILE IS GENERATED, DO NOT EDIT 172 173 use taler_macros::EnumMeta; 174 " 175 .to_string(); 176 177 for (set, enum_name) in [ 178 (domain, "BankTxDomainCode"), 179 (family, "BankTxFamilyCode"), 180 (subfamily, "BankTxSubFamilyCode"), 181 ] { 182 writeln!( 183 &mut out, 184 " 185 #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumMeta)] 186 #[enum_meta(Description, Str)] 187 pub enum {enum_name} {{ 188 " 189 ) 190 .unwrap(); 191 for (code, description) in set.iter() { 192 writeln!(&mut out, "/// {description}").unwrap(); 193 writeln!(&mut out, "{code},").unwrap(); 194 } 195 writeln!(&mut out, "}}").unwrap(); 196 } 197 std::fs::write("libeufin-ebics/src/iso20022/bank_tx_code.rs", out).unwrap(); 198 } 199 200 #[tokio::main] 201 pub async fn main() { 202 join!( 203 iso20022codegen_external_code_set(), 204 iso20022codegen_bank_transaction_code() 205 ); 206 }