libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

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 }