            Self::Romania => CountryAlpha3::ROU,
            Self::RussianFederation => CountryAlpha3::RUS,
            Self::Rwanda => CountryAlpha3::RWA,
            Self::SaintBarthelemy => CountryAlpha3::BLM,
            Self::SaintHelenaAscensionAndTristandaCunha => CountryAlpha3::SHN,
            Self::SaintKittsAndNevis => CountryAlpha3::KNA,
            Self::SaintLucia => CountryAlpha3::LCA,
            Self::SaintMartinFrenchpart => CountryAlpha3::MAF,
            Self::SaintPierreAndMiquelon => CountryAlpha3::SPM,
            Self::SaintVincentAndTheGrenadines => CountryAlpha3::VCT,
            Self::Samoa => CountryAlpha3::WSM,
            Self::SanMarino => CountryAlpha3::SMR,
            Self::SaoTomeAndPrincipe => CountryAlpha3::STP,
            Self::SaudiArabia => CountryAlpha3::SAU,
            Self::Senegal => CountryAlpha3::SEN,
            Self::Serbia => CountryAlpha3::SRB,
            Self::Seychelles => CountryAlpha3::SYC,
            Self::SierraLeone => CountryAlpha3::SLE,
            Self::Singapore => CountryAlpha3::SGP,
            Self::SintMaartenDutchpart => CountryAlpha3::SXM,
            Self::Slovakia => CountryAlpha3::SVK,
            Self::Slovenia => CountryAlpha3::SVN,
            Self::SolomonIslands => CountryAlpha3::SLB,
            Self::Somalia => CountryAlpha3::SOM,
            Self::SouthAfrica => CountryAlpha3::ZAF,
            Self::SouthGeorgiaAndTheSouthSandwichIslands => CountryAlpha3::SGS,
            Self::SouthSudan => CountryAlpha3::SSD,
            Self::Spain => CountryAlpha3::ESP,
            Self::SriLanka => CountryAlpha3::LKA,
            Self::Sudan => CountryAlpha3::SDN,
            Self::Suriname => CountryAlpha3::SUR,
            Self::SvalbardAndJanMayen => CountryAlpha3::SJM,
            Self::Swaziland => CountryAlpha3::SWZ,
            Self::Sweden => CountryAlpha3::SWE,
            Self::Switzerland => CountryAlpha3::CHE,
            Self::SyrianArabRepublic => CountryAlpha3::SYR,
            Self::TaiwanProvinceOfChina => CountryAlpha3::TWN,
            Self::Tajikistan => CountryAlpha3::TJK,
            Self::TanzaniaUnitedRepublic => CountryAlpha3::TZA,
            Self::Thailand => CountryAlpha3::THA,
            Self::TimorLeste => CountryAlpha3::TLS,
            Self::Togo => CountryAlpha3::TGO,
            Self::Tokelau => CountryAlpha3::TKL,
            Self::Tonga => CountryAlpha3::TON,
            Self::TrinidadAndTobago => CountryAlpha3::TTO,
            Self::Tunisia => CountryAlpha3::TUN,
            Self::Turkey => CountryAlpha3::TUR,
            Self::Turkmenistan => CountryAlpha3::TKM,
            Self::TurksAndCaicosIslands => CountryAlpha3::TCA,
            Self::Tuvalu => CountryAlpha3::TUV,
            Self::Uganda => CountryAlpha3::UGA,
            Self::Ukraine => CountryAlpha3::UKR,
            Self::UnitedArabEmirates => CountryAlpha3::ARE,
            Self::UnitedKingdomOfGreatBritainAndNorthernIreland => CountryAlpha3::GBR,
            Self::UnitedStatesOfAmerica => CountryAlpha3::USA,
            Self::UnitedStatesMinorOutlyingIslands => CountryAlpha3::UMI,
            Self::Uruguay => CountryAlpha3::URY,
            Self::Uzbekistan => CountryAlpha3::UZB,
            Self::Vanuatu => CountryAlpha3::VUT,
            Self::VenezuelaBolivarianRepublic => CountryAlpha3::VEN,
            Self::Vietnam => CountryAlpha3::VNM,
            Self::VirginIslandsBritish => CountryAlpha3::VGB,
            Self::VirginIslandsUS => CountryAlpha3::VIR,
            Self::WallisAndFutuna => CountryAlpha3::WLF,
            Self::WesternSahara => CountryAlpha3::ESH,
            Self::Yemen => CountryAlpha3::YEM,
            Self::Zambia => CountryAlpha3::ZMB,
            Self::Zimbabwe => CountryAlpha3::ZWE,
        }
    }
    pub const fn from_numeric(code: u32) -> Result<Self, NumericCountryCodeParseError> {
        match code {
            4 => Ok(Self::Afghanistan),
            248 => Ok(Self::AlandIslands),
            8 => Ok(Self::Albania),
            12 => Ok(Self::Algeria),
            16 => Ok(Self::AmericanSamoa),
            20 => Ok(Self::Andorra),
            24 => Ok(Self::Angola),
            660 => Ok(Self::Anguilla),
            10 => Ok(Self::Antarctica),
            28 => Ok(Self::AntiguaAndBarbuda),
            32 => Ok(Self::Argentina),
            51 => Ok(Self::Armenia),
            533 => Ok(Self::Aruba),
            36 => Ok(Self::Australia),
            40 => Ok(Self::Austria),
            31 => Ok(Self::Azerbaijan),
            44 => Ok(Self::Bahamas),
            48 => Ok(Self::Bahrain),
            50 => Ok(Self::Bangladesh),
            52 => Ok(Self::Barbados),
            112 => Ok(Self::Belarus),
            56 => Ok(Self::Belgium),
            84 => Ok(Self::Belize),
            204 => Ok(Self::Benin),
            60 => Ok(Self::Bermuda),
            64 => Ok(Self::Bhutan),
            68 => Ok(Self::BoliviaPlurinationalState),
            535 => Ok(Self::BonaireSintEustatiusAndSaba),
            70 => Ok(Self::BosniaAndHerzegovina),
            72 => Ok(Self::Botswana),
            74 => Ok(Self::BouvetIsland),
            76 => Ok(Self::Brazil),
            86 => Ok(Self::BritishIndianOceanTerritory),
            96 => Ok(Self::BruneiDarussalam),
            100 => Ok(Self::Bulgaria),
            854 => Ok(Self::BurkinaFaso),
            108 => Ok(Self::Burundi),
            132 => Ok(Self::CaboVerde),
            116 => Ok(Self::Cambodia),
            120 => Ok(Self::Cameroon),
            124 => Ok(Self::Canada),
            136 => Ok(Self::CaymanIslands),
            140 => Ok(Self::CentralAfricanRepublic),
            148 => Ok(Self::Chad),
            152 => Ok(Self::Chile),
            156 => Ok(Self::China),
            162 => Ok(Self::ChristmasIsland),
            166 => Ok(Self::CocosKeelingIslands),
            170 => Ok(Self::Colombia),
            174 => Ok(Self::Comoros),
            178 => Ok(Self::Congo),
            180 => Ok(Self::CongoDemocraticRepublic),
            184 => Ok(Self::CookIslands),
            188 => Ok(Self::CostaRica),
            384 => Ok(Self::CotedIvoire),
            191 => Ok(Self::Croatia),
            192 => Ok(Self::Cuba),
            531 => Ok(Self::Curacao),
            196 => Ok(Self::Cyprus),
            203 => Ok(Self::Czechia),
            208 => Ok(Self::Denmark),
            262 => Ok(Self::Djibouti),
            212 => Ok(Self::Dominica),
            214 => Ok(Self::DominicanRepublic),
            218 => Ok(Self::Ecuador),
            818 => Ok(Self::Egypt),
            222 => Ok(Self::ElSalvador),
            226 => Ok(Self::EquatorialGuinea),
            232 => Ok(Self::Eritrea),
            233 => Ok(Self::Estonia),
            231 => Ok(Self::Ethiopia),
            238 => Ok(Self::FalklandIslandsMalvinas),
            234 => Ok(Self::FaroeIslands),
            242 => Ok(Self::Fiji),
            246 => Ok(Self::Finland),
            250 => Ok(Self::France),
            254 => Ok(Self::FrenchGuiana),
            258 => Ok(Self::FrenchPolynesia),
            260 => Ok(Self::FrenchSouthernTerritories),
            266 => Ok(Self::Gabon),
            270 => Ok(Self::Gambia),
            268 => Ok(Self::Georgia),
            276 => Ok(Self::Germany),
            288 => Ok(Self::Ghana),
            292 => Ok(Self::Gibraltar),
            300 => Ok(Self::Greece),
            304 => Ok(Self::Greenland),
            308 => Ok(Self::Grenada),
            312 => Ok(Self::Guadeloupe),
            316 => Ok(Self::Guam),
            320 => Ok(Self::Guatemala),
            831 => Ok(Self::Guernsey),
            324 => Ok(Self::Guinea),
            624 => Ok(Self::GuineaBissau),
            328 => Ok(Self::Guyana),
            332 => Ok(Self::Haiti),
            334 => Ok(Self::HeardIslandAndMcDonaldIslands),
            336 => Ok(Self::HolySee),
            340 => Ok(Self::Honduras),
            344 => Ok(Self::HongKong),
            348 => Ok(Self::Hungary),
            352 => Ok(Self::Iceland),
            356 => Ok(Self::India),
            360 => Ok(Self::Indonesia),
            364 => Ok(Self::IranIslamicRepublic),
            368 => Ok(Self::Iraq),
            372 => Ok(Self::Ireland),
            833 => Ok(Self::IsleOfMan),
            376 => Ok(Self::Israel),
            380 => Ok(Self::Italy),
            388 => Ok(Self::Jamaica),
            392 => Ok(Self::Japan),
            832 => Ok(Self::Jersey),
            400 => Ok(Self::Jordan),
            398 => Ok(Self::Kazakhstan),
            404 => Ok(Self::Kenya),
            296 => Ok(Self::Kiribati),
            408 => Ok(Self::KoreaDemocraticPeoplesRepublic),
            410 => Ok(Self::KoreaRepublic),
            414 => Ok(Self::Kuwait),
            417 => Ok(Self::Kyrgyzstan),
            418 => Ok(Self::LaoPeoplesDemocraticRepublic),
            428 => Ok(Self::Latvia),
            422 => Ok(Self::Lebanon),
            426 => Ok(Self::Lesotho),
            430 => Ok(Self::Liberia),
            434 => Ok(Self::Libya),
            438 => Ok(Self::Liechtenstein),
            440 => Ok(Self::Lithuania),
            442 => Ok(Self::Luxembourg),
            446 => Ok(Self::Macao),
            807 => Ok(Self::MacedoniaTheFormerYugoslavRepublic),
            450 => Ok(Self::Madagascar),
            454 => Ok(Self::Malawi),
            458 => Ok(Self::Malaysia),
            462 => Ok(Self::Maldives),
            466 => Ok(Self::Mali),
            470 => Ok(Self::Malta),
            584 => Ok(Self::MarshallIslands),
            474 => Ok(Self::Martinique),
            478 => Ok(Self::Mauritania),
            480 => Ok(Self::Mauritius),
            175 => Ok(Self::Mayotte),
            484 => Ok(Self::Mexico),
            583 => Ok(Self::MicronesiaFederatedStates),
            498 => Ok(Self::MoldovaRepublic),
            492 => Ok(Self::Monaco),
            496 => Ok(Self::Mongolia),
            499 => Ok(Self::Montenegro),
            500 => Ok(Self::Montserrat),
            504 => Ok(Self::Morocco),
            508 => Ok(Self::Mozambique),
            104 => Ok(Self::Myanmar),
            516 => Ok(Self::Namibia),
            520 => Ok(Self::Nauru),
            524 => Ok(Self::Nepal),
            528 => Ok(Self::Netherlands),
            540 => Ok(Self::NewCaledonia),
            554 => Ok(Self::NewZealand),
            558 => Ok(Self::Nicaragua),
            562 => Ok(Self::Niger),
            566 => Ok(Self::Nigeria),
            570 => Ok(Self::Niue),
            574 => Ok(Self::NorfolkIsland),
            580 => Ok(Self::NorthernMarianaIslands),
            578 => Ok(Self::Norway),
            512 => Ok(Self::Oman),
            586 => Ok(Self::Pakistan),
            585 => Ok(Self::Palau),
            275 => Ok(Self::PalestineState),
            591 => Ok(Self::Panama),
            598 => Ok(Self::PapuaNewGuinea),
            600 => Ok(Self::Paraguay),
            604 => Ok(Self::Peru),
            608 => Ok(Self::Philippines),
            612 => Ok(Self::Pitcairn),
            616 => Ok(Self::Poland),
            620 => Ok(Self::Portugal),
            630 => Ok(Self::PuertoRico),
            634 => Ok(Self::Qatar),
            638 => Ok(Self::Reunion),
            642 => Ok(Self::Romania),
            643 => Ok(Self::RussianFederation),
            646 => Ok(Self::Rwanda),
            652 => Ok(Self::SaintBarthelemy),
            654 => Ok(Self::SaintHelenaAscensionAndTristandaCunha),
            659 => Ok(Self::SaintKittsAndNevis),
            662 => Ok(Self::SaintLucia),
            663 => Ok(Self::SaintMartinFrenchpart),
            666 => Ok(Self::SaintPierreAndMiquelon),
            670 => Ok(Self::SaintVincentAndTheGrenadines),
            882 => Ok(Self::Samoa),
            674 => Ok(Self::SanMarino),
            678 => Ok(Self::SaoTomeAndPrincipe),
            682 => Ok(Self::SaudiArabia),
            686 => Ok(Self::Senegal),
            688 => Ok(Self::Serbia),
            690 => Ok(Self::Seychelles),
            694 => Ok(Self::SierraLeone),
            702 => Ok(Self::Singapore),
            534 => Ok(Self::SintMaartenDutchpart),
            703 => Ok(Self::Slovakia),
            705 => Ok(Self::Slovenia),
            90 => Ok(Self::SolomonIslands),
            706 => Ok(Self::Somalia),
            710 => Ok(Self::SouthAfrica),
            239 => Ok(Self::SouthGeorgiaAndTheSouthSandwichIslands),
            728 => Ok(Self::SouthSudan),
            724 => Ok(Self::Spain),
            144 => Ok(Self::SriLanka),
            729 => Ok(Self::Sudan),
            740 => Ok(Self::Suriname),
            744 => Ok(Self::SvalbardAndJanMayen),
            748 => Ok(Self::Swaziland),
            752 => Ok(Self::Sweden),
            756 => Ok(Self::Switzerland),
            760 => Ok(Self::SyrianArabRepublic),
            158 => Ok(Self::TaiwanProvinceOfChina),
            762 => Ok(Self::Tajikistan),
            834 => Ok(Self::TanzaniaUnitedRepublic),
            764 => Ok(Self::Thailand),
            626 => Ok(Self::TimorLeste),
            768 => Ok(Self::Togo),
            772 => Ok(Self::Tokelau),
            776 => Ok(Self::Tonga),
            780 => Ok(Self::TrinidadAndTobago),
            788 => Ok(Self::Tunisia),
            792 => Ok(Self::Turkey),
            795 => Ok(Self::Turkmenistan),
            796 => Ok(Self::TurksAndCaicosIslands),
            798 => Ok(Self::Tuvalu),
            800 => Ok(Self::Uganda),
            804 => Ok(Self::Ukraine),
            784 => Ok(Self::UnitedArabEmirates),
            826 => Ok(Self::UnitedKingdomOfGreatBritainAndNorthernIreland),
            840 => Ok(Self::UnitedStatesOfAmerica),
            581 => Ok(Self::UnitedStatesMinorOutlyingIslands),
            858 => Ok(Self::Uruguay),
            860 => Ok(Self::Uzbekistan),
            548 => Ok(Self::Vanuatu),
            862 => Ok(Self::VenezuelaBolivarianRepublic),
            704 => Ok(Self::Vietnam),
            92 => Ok(Self::VirginIslandsBritish),
            850 => Ok(Self::VirginIslandsUS),
            876 => Ok(Self::WallisAndFutuna),
            732 => Ok(Self::WesternSahara),
            887 => Ok(Self::Yemen),
            894 => Ok(Self::Zambia),
            716 => Ok(Self::Zimbabwe),
            _ => Err(NumericCountryCodeParseError),
        }
    }
    pub const fn to_numeric(self) -> u32 {
        match self {
            Self::Afghanistan => 4,
            Self::AlandIslands => 248,
            Self::Albania => 8,
            Self::Algeria => 12,
            Self::AmericanSamoa => 16,
            Self::Andorra => 20,
            Self::Angola => 24,
            Self::Anguilla => 660,
            Self::Antarctica => 10,
            Self::AntiguaAndBarbuda => 28,
            Self::Argentina => 32,
            Self::Armenia => 51,
            Self::Aruba => 533,
            Self::Australia => 36,
            Self::Austria => 40,
            Self::Azerbaijan => 31,
            Self::Bahamas => 44,
            Self::Bahrain => 48,
            Self::Bangladesh => 50,
            Self::Barbados => 52,
            Self::Belarus => 112,
            Self::Belgium => 56,
            Self::Belize => 84,
            Self::Benin => 204,
            Self::Bermuda => 60,
            Self::Bhutan => 64,
            Self::BoliviaPlurinationalState => 68,
            Self::BonaireSintEustatiusAndSaba => 535,
            Self::BosniaAndHerzegovina => 70,
            Self::Botswana => 72,
            Self::BouvetIsland => 74,
            Self::Brazil => 76,
            Self::BritishIndianOceanTerritory => 86,
            Self::BruneiDarussalam => 96,
            Self::Bulgaria => 100,
            Self::BurkinaFaso => 854,
            Self::Burundi => 108,
            Self::CaboVerde => 132,
            Self::Cambodia => 116,
            Self::Cameroon => 120,
            Self::Canada => 124,
            Self::CaymanIslands => 136,
            Self::CentralAfricanRepublic => 140,
            Self::Chad => 148,
            Self::Chile => 152,
            Self::China => 156,
            Self::ChristmasIsland => 162,
            Self::CocosKeelingIslands => 166,
            Self::Colombia => 170,
            Self::Comoros => 174,
            Self::Congo => 178,
            Self::CongoDemocraticRepublic => 180,
            Self::CookIslands => 184,
            Self::CostaRica => 188,
            Self::CotedIvoire => 384,
            Self::Croatia => 191,
            Self::Cuba => 192,
            Self::Curacao => 531,
            Self::Cyprus => 196,
            Self::Czechia => 203,
            Self::Denmark => 208,
            Self::Djibouti => 262,
            Self::Dominica => 212,
            Self::DominicanRepublic => 214,
            Self::Ecuador => 218,
            Self::Egypt => 818,
            Self::ElSalvador => 222,
            Self::EquatorialGuinea => 226,
            Self::Eritrea => 232,
            Self::Estonia => 233,
            Self::Ethiopia => 231,
            Self::FalklandIslandsMalvinas => 238,
            Self::FaroeIslands => 234,
            Self::Fiji => 242,
            Self::Finland => 246,
            Self::France => 250,
            Self::FrenchGuiana => 254,
            Self::FrenchPolynesia => 258,
            Self::FrenchSouthernTerritories => 260,
            Self::Gabon => 266,
            Self::Gambia => 270,
            Self::Georgia => 268,
            Self::Germany => 276,
            Self::Ghana => 288,
            Self::Gibraltar => 292,
            Self::Greece => 300,
            Self::Greenland => 304,
            Self::Grenada => 308,
            Self::Guadeloupe => 312,
            Self::Guam => 316,
            Self::Guatemala => 320,
            Self::Guernsey => 831,
            Self::Guinea => 324,
            Self::GuineaBissau => 624,
            Self::Guyana => 328,
            Self::Haiti => 332,
            Self::HeardIslandAndMcDonaldIslands => 334,
            Self::HolySee => 336,
            Self::Honduras => 340,
            Self::HongKong => 344,
            Self::Hungary => 348,
            Self::Iceland => 352,
            Self::India => 356,
            Self::Indonesia => 360,
            Self::IranIslamicRepublic => 364,
            Self::Iraq => 368,
            Self::Ireland => 372,
            Self::IsleOfMan => 833,
            Self::Israel => 376,
            Self::Italy => 380,
            Self::Jamaica => 388,
            Self::Japan => 392,
            Self::Jersey => 832,
            Self::Jordan => 400,
            Self::Kazakhstan => 398,
            Self::Kenya => 404,
            Self::Kiribati => 296,
            Self::KoreaDemocraticPeoplesRepublic => 408,
            Self::KoreaRepublic => 410,
            Self::Kuwait => 414,
            Self::Kyrgyzstan => 417,
            Self::LaoPeoplesDemocraticRepublic => 418,
            Self::Latvia => 428,
            Self::Lebanon => 422,
            Self::Lesotho => 426,
            Self::Liberia => 430,
            Self::Libya => 434,
            Self::Liechtenstein => 438,
            Self::Lithuania => 440,
            Self::Luxembourg => 442,
            Self::Macao => 446,
            Self::MacedoniaTheFormerYugoslavRepublic => 807,
            Self::Madagascar => 450,
            Self::Malawi => 454,
            Self::Malaysia => 458,
            Self::Maldives => 462,
            Self::Mali => 466,
            Self::Malta => 470,
            Self::MarshallIslands => 584,
            Self::Martinique => 474,
            Self::Mauritania => 478,
            Self::Mauritius => 480,
            Self::Mayotte => 175,
            Self::Mexico => 484,
            Self::MicronesiaFederatedStates => 583,
            Self::MoldovaRepublic => 498,
            Self::Monaco => 492,
            Self::Mongolia => 496,
            Self::Montenegro => 499,
            Self::Montserrat => 500,
            Self::Morocco => 504,
            Self::Mozambique => 508,
            Self::Myanmar => 104,
            Self::Namibia => 516,
            Self::Nauru => 520,
            Self::Nepal => 524,
            Self::Netherlands => 528,
            Self::NewCaledonia => 540,
            Self::NewZealand => 554,
            Self::Nicaragua => 558,
            Self::Niger => 562,
            Self::Nigeria => 566,
            Self::Niue => 570,
            Self::NorfolkIsland => 574,
            Self::NorthernMarianaIslands => 580,
            Self::Norway => 578,
            Self::Oman => 512,
            Self::Pakistan => 586,
            Self::Palau => 585,
            Self::PalestineState => 275,
            Self::Panama => 591,
            Self::PapuaNewGuinea => 598,
            Self::Paraguay => 600,
            Self::Peru => 604,
            Self::Philippines => 608,
            Self::Pitcairn => 612,
            Self::Poland => 616,
            Self::Portugal => 620,
            Self::PuertoRico => 630,
            Self::Qatar => 634,
            Self::Reunion => 638,
            Self::Romania => 642,
            Self::RussianFederation => 643,
            Self::Rwanda => 646,
            Self::SaintBarthelemy => 652,
            Self::SaintHelenaAscensionAndTristandaCunha => 654,
            Self::SaintKittsAndNevis => 659,
            Self::SaintLucia => 662,
            Self::SaintMartinFrenchpart => 663,
            Self::SaintPierreAndMiquelon => 666,
            Self::SaintVincentAndTheGrenadines => 670,
            Self::Samoa => 882,
            Self::SanMarino => 674,
            Self::SaoTomeAndPrincipe => 678,
            Self::SaudiArabia => 682,
            Self::Senegal => 686,
            Self::Serbia => 688,
            Self::Seychelles => 690,
            Self::SierraLeone => 694,
            Self::Singapore => 702,
            Self::SintMaartenDutchpart => 534,
            Self::Slovakia => 703,
            Self::Slovenia => 705,
            Self::SolomonIslands => 90,
            Self::Somalia => 706,
            Self::SouthAfrica => 710,
            Self::SouthGeorgiaAndTheSouthSandwichIslands => 239,
            Self::SouthSudan => 728,
            Self::Spain => 724,
            Self::SriLanka => 144,
            Self::Sudan => 729,
            Self::Suriname => 740,
            Self::SvalbardAndJanMayen => 744,
            Self::Swaziland => 748,
            Self::Sweden => 752,
            Self::Switzerland => 756,
            Self::SyrianArabRepublic => 760,
            Self::TaiwanProvinceOfChina => 158,
            Self::Tajikistan => 762,
            Self::TanzaniaUnitedRepublic => 834,
            Self::Thailand => 764,
            Self::TimorLeste => 626,
            Self::Togo => 768,
            Self::Tokelau => 772,
            Self::Tonga => 776,
            Self::TrinidadAndTobago => 780,
            Self::Tunisia => 788,
            Self::Turkey => 792,
            Self::Turkmenistan => 795,
            Self::TurksAndCaicosIslands => 796,
            Self::Tuvalu => 798,
            Self::Uganda => 800,
            Self::Ukraine => 804,
            Self::UnitedArabEmirates => 784,
            Self::UnitedKingdomOfGreatBritainAndNorthernIreland => 826,
            Self::UnitedStatesOfAmerica => 840,
            Self::UnitedStatesMinorOutlyingIslands => 581,
            Self::Uruguay => 858,
            Self::Uzbekistan => 860,
            Self::Vanuatu => 548,
            Self::VenezuelaBolivarianRepublic => 862,
            Self::Vietnam => 704,
            Self::VirginIslandsBritish => 92,
            Self::VirginIslandsUS => 850,
            Self::WallisAndFutuna => 876,
            Self::WesternSahara => 732,
            Self::Yemen => 887,
            Self::Zambia => 894,
            Self::Zimbabwe => 716,
        }
    }
}

impl From<PaymentMethodType> for PaymentMethod {
    fn from(value: PaymentMethodType) -> Self {
        match value {
            PaymentMethodType::Ach => Self::BankDebit,
            PaymentMethodType::Affirm => Self::PayLater,
            PaymentMethodType::AfterpayClearpay => Self::PayLater,
            PaymentMethodType::AliPay => Self::Wallet,
            PaymentMethodType::AliPayHk => Self::Wallet,
            PaymentMethodType::Alma => Self::PayLater,
            PaymentMethodType::AmazonPay => Self::Wallet,
            PaymentMethodType::Paysera => Self::Wallet,
            PaymentMethodType::Skrill => Self::Wallet,
            PaymentMethodType::ApplePay => Self::Wallet,
            PaymentMethodType::Bacs => Self::BankDebit,
            PaymentMethodType::BancontactCard => Self::BankRedirect,
            PaymentMethodType::BcaBankTransfer => Self::BankTransfer,
            PaymentMethodType::Becs => Self::BankDebit,
            PaymentMethodType::BniVa => Self::BankTransfer,
            PaymentMethodType::Breadpay => Self::PayLater,
            PaymentMethodType::BriVa => Self::BankTransfer,
            PaymentMethodType::Benefit => Self::CardRedirect,
            PaymentMethodType::Bizum => Self::BankRedirect,
            PaymentMethodType::Blik => Self::BankRedirect,
            PaymentMethodType::Bluecode => Self::Wallet,
            PaymentMethodType::Alfamart => Self::Voucher,
            PaymentMethodType::CardRedirect => Self::CardRedirect,
            PaymentMethodType::CimbVa => Self::BankTransfer,
            PaymentMethodType::ClassicReward => Self::Reward,
            PaymentMethodType::Credit => Self::Card,
            #[cfg(feature = "v2")]
            PaymentMethodType::Card => Self::Card,
            PaymentMethodType::CryptoCurrency => Self::Crypto,
            PaymentMethodType::Dana => Self::Wallet,
            PaymentMethodType::DanamonVa => Self::BankTransfer,
            PaymentMethodType::Debit => Self::Card,
            PaymentMethodType::Flexiti => Self::PayLater,
            PaymentMethodType::Fps => Self::RealTimePayment,
            PaymentMethodType::DuitNow => Self::RealTimePayment,
            PaymentMethodType::Eft => Self::BankRedirect,
            PaymentMethodType::Eps => Self::BankRedirect,
            PaymentMethodType::Evoucher => Self::Reward,
            PaymentMethodType::Giropay => Self::BankRedirect,
            PaymentMethodType::GooglePay => Self::Wallet,
            PaymentMethodType::GoPay => Self::Wallet,
            PaymentMethodType::Gcash => Self::Wallet,
            PaymentMethodType::Mifinity => Self::Wallet,
            PaymentMethodType::Ideal => Self::BankRedirect,
            PaymentMethodType::Klarna => Self::PayLater,
            PaymentMethodType::KakaoPay => Self::Wallet,
            PaymentMethodType::Knet => Self::CardRedirect,
            PaymentMethodType::LocalBankRedirect => Self::BankRedirect,
            PaymentMethodType::MbWay => Self::Wallet,
            PaymentMethodType::MobilePay => Self::Wallet,
            PaymentMethodType::Momo => Self::Wallet,
            PaymentMethodType::MomoAtm => Self::CardRedirect,
            PaymentMethodType::Multibanco => Self::BankTransfer,
            PaymentMethodType::MandiriVa => Self::BankTransfer,
            PaymentMethodType::Interac => Self::BankRedirect,
            PaymentMethodType::InstantBankTransfer => Self::BankTransfer,
            PaymentMethodType::InstantBankTransferFinland => Self::BankTransfer,
            PaymentMethodType::InstantBankTransferPoland => Self::BankTransfer,
            PaymentMethodType::Indomaret => Self::Voucher,
            PaymentMethodType::OnlineBankingCzechRepublic => Self::BankRedirect,
            PaymentMethodType::OnlineBankingFinland => Self::BankRedirect,


pub struct Order {
    pub amount_of_money: AmountOfMoney,
    pub customer: Customer,
    pub references: References,
}


pub async fn check_hard_decline(
    state: &SessionState,
    payment_attempt: &payment_attempt::PaymentAttempt,
) -> Result<bool, error_stack::Report<storage_impl::errors::RecoveryError>> {
    let error_message = payment_attempt
        .error
        .as_ref()
        .map(|details| details.message.clone());

    let error_code = payment_attempt
        .error
        .as_ref()
        .map(|details| details.code.clone());

    let connector_name = payment_attempt
        .connector
        .clone()
        .ok_or(storage_impl::errors::RecoveryError::ValueNotFound)
        .attach_printable("unable to derive payment connector from payment attempt")?;

    let gsm_record = payments::helpers::get_gsm_record(
        state,
        error_code,
        error_message,
        connector_name,
        REVENUE_RECOVERY.to_string(),
    )
    .await;

    let is_hard_decline = gsm_record
        .and_then(|record| record.error_category)
        .map(|category| category == common_enums::ErrorCategory::HardDecline)
        .unwrap_or(false);

    Ok(is_hard_decline)
}


impl ConnectorSpecifications for Itaubank {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&ITAUBANK_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*ITAUBANK_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&ITAUBANK_SUPPORTED_WEBHOOK_FLOWS)
    }
}

impl ConnectorSpecifications for for Itaubank


pub fn get_decision_engine_configs(
        &self,
    ) -> Result<open_router::DecisionEngineEliminationData, error_stack::Report<ValidationError>>
    {
        self.decision_engine_configs
            .clone()
            .ok_or(error_stack::Report::new(
                ValidationError::MissingRequiredField {
                    field_name: "decision_engine_configs".to_string(),
                },
            ))
    }


pub async fn do_status_check_for_network_token(
    state: &routes::SessionState,
    payment_method_info: &domain::PaymentMethod,
) -> CustomResult<(Option<Secret<String>>, Option<Secret<String>>), errors::ApiErrorResponse> {
    let network_token_data_decrypted = payment_method_info
        .network_token_payment_method_data
        .clone()
        .map(|x| x.into_inner().expose())
        .and_then(|v| serde_json::from_value::<api_payment_methods::PaymentMethodsData>(v).ok())
        .and_then(|pmd| match pmd {
            api_payment_methods::PaymentMethodsData::Card(token) => {
                Some(api::CardDetailFromLocker::from(token))
            }
            _ => None,
        });
    let network_token_requestor_reference_id = payment_method_info
        .network_token_requestor_reference_id
        .clone();
    if network_token_data_decrypted
        .and_then(|token_data| token_data.expiry_month.zip(token_data.expiry_year))
        .and_then(|(exp_month, exp_year)| helpers::validate_card_expiry(&exp_month, &exp_year).ok())
        .is_none()
    {
        if let Some(ref_id) = network_token_requestor_reference_id {
            if let Some(network_tokenization_service) = &state.conf.network_tokenization_service {
                let (token_exp_month, token_exp_year) = record_operation_time(
                    async {
                        check_token_status_with_tokenization_service(
                            state,
                            &payment_method_info.customer_id.clone(),
                            ref_id,
                            network_tokenization_service.get_inner(),
                        )
                        .await
                        .inspect_err(
                            |e| logger::error!(error=?e, "Error while fetching token from tokenization service")
                        )
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable(
                            "Check network token status with tokenization service failed",
                        )
                    },
                    &metrics::CHECK_NETWORK_TOKEN_STATUS_TIME,

                    &[],
                )
                .await?;
                Ok((token_exp_month, token_exp_year))
            } else {
                Err(errors::NetworkTokenizationError::NetworkTokenizationServiceNotConfigured)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .inspect_err(|_| {
                        logger::error!("Network Tokenization Service not configured");
                    })
            }
        } else {
            Err(errors::NetworkTokenizationError::FetchNetworkTokenFailed)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Check network token status failed")?
        }
    } else {
        Ok((None, None))
    }
}


impl IncomingWebhookEvent {
    /// Convert UCS event type integer to IncomingWebhookEvent
    /// Maps from proto WebhookEventType enum values to IncomingWebhookEvent variants
    pub fn from_ucs_event_type(event_type: i32) -> Self {
        match event_type {
            0 => Self::EventNotSupported,
            // Payment intent events
            1 => Self::PaymentIntentFailure,
            2 => Self::PaymentIntentSuccess,
            3 => Self::PaymentIntentProcessing,
            4 => Self::PaymentIntentPartiallyFunded,
            5 => Self::PaymentIntentCancelled,
            6 => Self::PaymentIntentCancelFailure,
            7 => Self::PaymentIntentAuthorizationSuccess,
            8 => Self::PaymentIntentAuthorizationFailure,
            9 => Self::PaymentIntentCaptureSuccess,
            10 => Self::PaymentIntentCaptureFailure,
            11 => Self::PaymentIntentExpired,
            12 => Self::PaymentActionRequired,
            // Source events
            13 => Self::SourceChargeable,
            14 => Self::SourceTransactionCreated,
            // Refund events
            15 => Self::RefundFailure,
            16 => Self::RefundSuccess,
            // Dispute events
            17 => Self::DisputeOpened,
            18 => Self::DisputeExpired,
            19 => Self::DisputeAccepted,
            20 => Self::DisputeCancelled,
            21 => Self::DisputeChallenged,
            22 => Self::DisputeWon,
            23 => Self::DisputeLost,
            // Mandate events
            24 => Self::MandateActive,
            25 => Self::MandateRevoked,
            // Miscellaneous events
            26 => Self::EndpointVerification,
            27 => Self::ExternalAuthenticationARes,
            28 => Self::FrmApproved,
            29 => Self::FrmRejected,
            // Payout events
            #[cfg(feature = "payouts")]
            30 => Self::PayoutSuccess,
            #[cfg(feature = "payouts")]
            31 => Self::PayoutFailure,
            #[cfg(feature = "payouts")]
            32 => Self::PayoutProcessing,
            #[cfg(feature = "payouts")]
            33 => Self::PayoutCancelled,
            #[cfg(feature = "payouts")]
            34 => Self::PayoutCreated,
            #[cfg(feature = "payouts")]
            35 => Self::PayoutExpired,
            #[cfg(feature = "payouts")]
            36 => Self::PayoutReversed,
            _ => Self::EventNotSupported,
        }
    }
}


pub struct NexinetsBankRedirects {
    bic: Option<NexinetsBIC>,
}


pub fn get_dispute_metrics_info() -> Vec<NameDescription> {
    DisputeMetrics::iter().map(Into::into).collect()
}


pub async fn external_vault_proxy_for_payments_operation_core<F, Req, Op, FData, D>(
    state: &SessionState,
    req_state: ReqState,
    merchant_context: domain::MerchantContext,
    profile: domain::Profile,
    operation: Op,
    req: Req,
    get_tracker_response: operations::GetTrackerResponse<D>,
    call_connector_action: CallConnectorAction,
    header_payload: HeaderPayload,
    return_raw_connector_response: Option<bool>,
) -> RouterResult<(D, Req, Option<u16>, Option<u128>)>
where
    F: Send + Clone + Sync,
    Req: Send + Sync + Authenticate,
    Op: Operation<F, Req, Data = D> + Send + Sync,
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,

    // To create connector flow specific interface data
    D: ConstructFlowSpecificData<F, FData, router_types::PaymentsResponseData>,
    RouterData<F, FData, router_types::PaymentsResponseData>: Feature<F, FData>,

    // To construct connector flow specific api
    dyn api::Connector:
        services::api::ConnectorIntegration<F, FData, router_types::PaymentsResponseData>,

    RouterData<F, FData, router_types::PaymentsResponseData>:
        hyperswitch_domain_models::router_data::TrackerPostUpdateObjects<F, FData, D>,

    // To perform router related operation for PaymentResponse
    PaymentResponse: Operation<F, FData, Data = D>,
    FData: Send + Sync + Clone,
{
    let operation: BoxedOperation<'_, F, Req, D> = Box::new(operation);

    // Get the trackers related to track the state of the payment
    let operations::GetTrackerResponse { mut payment_data } = get_tracker_response;

    let (_operation, customer) = operation
        .to_domain()?
        .get_customer_details(
            state,
            &mut payment_data,
            merchant_context.get_merchant_key_store(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)
        .attach_printable("Failed while fetching/creating customer")?;

    operation
        .to_domain()?
        .create_or_fetch_payment_method(state, &merchant_context, &profile, &mut payment_data)
        .await?;

    // consume the req merchant_connector_id and set it in the payment_data
    let connector = operation
        .to_domain()?
        .perform_routing(&merchant_context, &profile, state, &mut payment_data)
        .await?;

    let payment_data = match connector {
        ConnectorCallType::PreDetermined(connector_data) => {
            let (mca_type_details, external_vault_mca_type_details, updated_customer, router_data) =
                call_connector_service_prerequisites_for_external_vault_proxy(
                    state,
                    req_state.clone(),
                    &merchant_context,
                    connector_data.connector_data.clone(),
                    &operation,
                    &mut payment_data,
                    &customer,
                    call_connector_action.clone(),
                    None,
                    header_payload.clone(),
                    None,
                    &profile,
                    false,
                    false, //should_retry_with_pan is set to false in case of PreDetermined ConnectorCallType
                    req.should_return_raw_response(),
                )
                .await?;

            let router_data = call_unified_connector_service_for_external_proxy(
                state,
                req_state.clone(),
                &merchant_context,
                connector_data.connector_data.clone(),
                &operation,
                &mut payment_data,
                &customer,
                call_connector_action.clone(),
                None, // schedule_time is not used in PreDetermined ConnectorCallType
                header_payload.clone(),
                #[cfg(feature = "frm")]
                None,
                &profile,
                false,
                false, //should_retry_with_pan is set to false in case of PreDetermined ConnectorCallType
                req.should_return_raw_response(),
                mca_type_details,
                external_vault_mca_type_details,
                router_data,
                updated_customer,
            )
            .await?;

            // update payment method if its a successful transaction
            if router_data.status.is_success() {
                operation
                    .to_domain()?
                    .update_payment_method(state, &merchant_context, &mut payment_data)
                    .await;
            }

            let payments_response_operation = Box::new(PaymentResponse);

            payments_response_operation
                .to_post_update_tracker()?
                .update_tracker(
                    state,
                    payment_data,
                    router_data,
                    merchant_context.get_merchant_key_store(),
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await?
        }
        ConnectorCallType::Retryable(_) => todo!(),
        ConnectorCallType::SessionMultiple(_) => todo!(),
        ConnectorCallType::Skip => payment_data,
    };

    Ok((payment_data, req, None, None))
}


pub struct Hypersense;


OpenAPI Block Path: components.schemas.PayoutMethodData
{
  "oneOf": [
    {
      "type": "object",
      "required": [
        "card"
      ],
      "properties": {
        "card": {
          "$ref": "#/components/schemas/CardPayout"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "bank"
      ],
      "properties": {
        "bank": {
          "$ref": "#/components/schemas/Bank"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "wallet"
      ],
      "properties": {
        "wallet": {
          "$ref": "#/components/schemas/Wallet"
        }
      }
    }
  ],
  "description": "The payout method information required for carrying out a payout"
}


pub struct PaymentMethod {
    pub apm: Option<Apm>,
    pub card: Option<Card>,
    pub id: Option<Secret<String>>,
    pub message: Option<String>,
    pub result: Option<String>,
}


impl api::PaymentAuthorize for Blackhawknetwork {}

impl api::PaymentAuthorize for for Blackhawknetwork


pub fn new() -> &'static Self {
        &Self {
            amount_converter: &MinorUnitForConnector,
        }
    }


    // Algorithm was in disabled state
    let Some(algo_type_algorithm_id) = algo_type
        .clone()
        .get_algorithm_id_with_timestamp()
        .algorithm_id
    else {
        return default_specific_dynamic_routing_setup(
            state,
            key_store,
            business_profile,
            feature_to_enable,
            dynamic_routing_algo_ref,
            dynamic_routing_type,
        )
        .await;
    };
    let db = state.store.as_ref();
    let profile_id = business_profile.get_id().clone();
    let algo_type_enabled_features = algo_type.get_enabled_features();
    if *algo_type_enabled_features == feature_to_enable {
        // algorithm already has the required feature
        let routing_algorithm = db
            .find_routing_algorithm_by_profile_id_algorithm_id(&profile_id, &algo_type_algorithm_id)
            .await
            .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
        let updated_routing_record = routing_algorithm.foreign_into();

        return Ok(ApplicationResponse::Json(updated_routing_record));
    };
    *algo_type_enabled_features = feature_to_enable;
    dynamic_routing_algo_ref.update_enabled_features(dynamic_routing_type, feature_to_enable);
    update_business_profile_active_dynamic_algorithm_ref(
        db,
        &state.into(),
        &key_store,
        business_profile,
        dynamic_routing_algo_ref.clone(),
    )
    .await?;

    let routing_algorithm = db
        .find_routing_algorithm_by_profile_id_algorithm_id(&profile_id, &algo_type_algorithm_id)
        .await
        .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
    let updated_routing_record = routing_algorithm.foreign_into();
    core_metrics::ROUTING_CREATE_SUCCESS_RESPONSE.add(
        1,
        router_env::metric_attributes!(("profile_id", profile_id.clone())),
    );
    Ok(ApplicationResponse::Json(updated_routing_record))
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn default_specific_dynamic_routing_setup(
    state: &SessionState,
    key_store: domain::MerchantKeyStore,
    business_profile: domain::Profile,
    feature_to_enable: routing_types::DynamicRoutingFeatures,
    mut dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    dynamic_routing_type: routing_types::DynamicRoutingType,
) -> RouterResult<ApplicationResponse<routing_types::RoutingDictionaryRecord>> {
    let db = state.store.as_ref();
    let key_manager_state = &state.into();
    let profile_id = business_profile.get_id().clone();
    let merchant_id = business_profile.merchant_id.clone();
    let algorithm_id = common_utils::generate_routing_id_of_default_length();
    let timestamp = common_utils::date_time::now();

    let algo = match dynamic_routing_type {
        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
            let default_success_based_routing_config =
                if state.conf.open_router.dynamic_routing_enabled {
                    routing_types::SuccessBasedRoutingConfig::open_router_config_default()
                } else {
                    routing_types::SuccessBasedRoutingConfig::default()
                };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: SUCCESS_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(default_success_based_routing_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }
        routing_types::DynamicRoutingType::EliminationRouting => {
            let default_elimination_routing_config =
                if state.conf.open_router.dynamic_routing_enabled {
                    routing_types::EliminationRoutingConfig::open_router_config_default()
                } else {
                    routing_types::EliminationRoutingConfig::default()
                };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: ELIMINATION_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(default_elimination_routing_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }

        routing_types::DynamicRoutingType::ContractBasedRouting => {
            return Err((errors::ApiErrorResponse::InvalidRequestData {
                message: "Contract routing cannot be set as default".to_string(),
            })
            .into())
        }
    };

    // Call to DE here
    // Need to map out the cases if this call should always be made or not
    if state.conf.open_router.dynamic_routing_enabled {
        enable_decision_engine_dynamic_routing_setup(
            state,
            business_profile.get_id(),
            dynamic_routing_type,
            &mut dynamic_routing_algo_ref,
            None,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to setup decision engine dynamic routing")?;
    }

    let record = db
        .insert_routing_algorithm(algo)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to insert record in routing algorithm table")?;

    dynamic_routing_algo_ref.update_algorithm_id(
        algorithm_id,
        feature_to_enable,
        dynamic_routing_type,
    );
    update_business_profile_active_dynamic_algorithm_ref(
        db,
        key_manager_state,
        &key_store,
        business_profile,
        dynamic_routing_algo_ref,
    )
    .await?;

    let new_record = record.foreign_into();

    core_metrics::ROUTING_CREATE_SUCCESS_RESPONSE.add(
        1,
        router_env::metric_attributes!(("profile_id", profile_id.clone())),
    );
    Ok(ApplicationResponse::Json(new_record))
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn create_specific_dynamic_routing_setup(
    state: &SessionState,
    key_store: domain::MerchantKeyStore,
    business_profile: domain::Profile,
    feature_to_enable: routing_types::DynamicRoutingFeatures,
    mut dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    dynamic_routing_type: routing_types::DynamicRoutingType,
    payload: routing_types::DynamicRoutingPayload,
) -> RouterResult<ApplicationResponse<routing_types::RoutingDictionaryRecord>> {
    let db = state.store.as_ref();
    let key_manager_state = &state.into();
    let profile_id = business_profile.get_id().clone();
    let merchant_id = business_profile.merchant_id.clone();
    let algorithm_id = common_utils::generate_routing_id_of_default_length();
    let timestamp = common_utils::date_time::now();

    let algo = match dynamic_routing_type {
        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
            let success_config = match &payload {
                routing_types::DynamicRoutingPayload::SuccessBasedRoutingPayload(config) => config,
                _ => {
                    return Err((errors::ApiErrorResponse::InvalidRequestData {
                        message: "Invalid payload type for Success Rate Based Routing".to_string(),
                    })
                    .into())
                }
            };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: SUCCESS_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(success_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }
        routing_types::DynamicRoutingType::EliminationRouting => {
            let elimination_config = match &payload {
                routing_types::DynamicRoutingPayload::EliminationRoutingPayload(config) => config,
                _ => {
                    return Err((errors::ApiErrorResponse::InvalidRequestData {
                        message: "Invalid payload type for Elimination Routing".to_string(),
                    })
                    .into())
                }
            };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: ELIMINATION_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(elimination_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }

        routing_types::DynamicRoutingType::ContractBasedRouting => {
            return Err((errors::ApiErrorResponse::InvalidRequestData {
                message: "Contract routing cannot be set as default".to_string(),
            })
            .into())
        }
    };

    let record = db
        .insert_routing_algorithm(algo)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to insert record in routing algorithm table")?;

    dynamic_routing_algo_ref.update_feature(feature_to_enable, dynamic_routing_type);
    update_business_profile_active_dynamic_algorithm_ref(
        db,
        key_manager_state,
        &key_store,
        business_profile,
        dynamic_routing_algo_ref,
    )
    .await?;

    let new_record = record.foreign_into();

    core_metrics::ROUTING_CREATE_SUCCESS_RESPONSE.add(
        1,
        router_env::metric_attributes!(("profile_id", profile_id.clone())),
    );
    Ok(ApplicationResponse::Json(new_record))
}

#[derive(Debug, Clone)]
pub struct DynamicRoutingConfigParamsInterpolator {
    pub payment_method: Option<common_enums::PaymentMethod>,
    pub payment_method_type: Option<common_enums::PaymentMethodType>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub currency: Option<common_enums::Currency>,
    pub country: Option<common_enums::CountryAlpha2>,
    pub card_network: Option<String>,
    pub card_bin: Option<String>,
}

impl DynamicRoutingConfigParamsInterpolator {
    pub fn new(
        payment_method: Option<common_enums::PaymentMethod>,
        payment_method_type: Option<common_enums::PaymentMethodType>,
        authentication_type: Option<common_enums::AuthenticationType>,
        currency: Option<common_enums::Currency>,
        country: Option<common_enums::CountryAlpha2>,
        card_network: Option<String>,
        card_bin: Option<String>,
    ) -> Self {
        Self {
            payment_method,
            payment_method_type,
            authentication_type,
            currency,
            country,
            card_network,
            card_bin,
        }
    }

    pub fn get_string_val(
        &self,
        params: &Vec<routing_types::DynamicRoutingConfigParams>,
    ) -> String {
        let mut parts: Vec<String> = Vec::new();
        for param in params {
            let val = match param {
                routing_types::DynamicRoutingConfigParams::PaymentMethod => self
                    .payment_method
                    .as_ref()
                    .map_or(String::new(), |pm| pm.to_string()),
                routing_types::DynamicRoutingConfigParams::PaymentMethodType => self
                    .payment_method_type
                    .as_ref()
                    .map_or(String::new(), |pmt| pmt.to_string()),
                routing_types::DynamicRoutingConfigParams::AuthenticationType => self
                    .authentication_type
                    .as_ref()
                    .map_or(String::new(), |at| at.to_string()),
                routing_types::DynamicRoutingConfigParams::Currency => self
                    .currency
                    .as_ref()
                    .map_or(String::new(), |cur| cur.to_string()),
                routing_types::DynamicRoutingConfigParams::Country => self
                    .country
                    .as_ref()
                    .map_or(String::new(), |cn| cn.to_string()),
                routing_types::DynamicRoutingConfigParams::CardNetwork => {
                    self.card_network.clone().unwrap_or_default()
                }
                routing_types::DynamicRoutingConfigParams::CardBin => {
                    self.card_bin.clone().unwrap_or_default()
                }
            };
            if !val.is_empty() {
                parts.push(val);
            }
        }
        parts.join(":")
    }
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn enable_decision_engine_dynamic_routing_setup(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    dynamic_routing_type: routing_types::DynamicRoutingType,
    dynamic_routing_algo_ref: &mut routing_types::DynamicRoutingAlgorithmRef,
    payload: Option<routing_types::DynamicRoutingPayload>,
) -> RouterResult<()> {
    logger::debug!(
        "performing call with open_router for profile {}",
        profile_id.get_string_repr()
    );

    let decision_engine_config_request = match dynamic_routing_type {
        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
            let success_based_routing_config = payload
                .and_then(|p| match p {
                    routing_types::DynamicRoutingPayload::SuccessBasedRoutingPayload(config) => {
                        Some(config)
                    }
                    _ => None,
                })
                .unwrap_or_else(
                    routing_types::SuccessBasedRoutingConfig::open_router_config_default,
                );

            open_router::DecisionEngineConfigSetupRequest {
                merchant_id: profile_id.get_string_repr().to_string(),
                config: open_router::DecisionEngineConfigVariant::SuccessRate(
                    success_based_routing_config
                        .get_decision_engine_configs()
                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                            message: "Decision engine config not found".to_string(),
                        })
                        .attach_printable("Decision engine config not found")?,
                ),
            }
        }
        routing_types::DynamicRoutingType::EliminationRouting => {
            let elimination_based_routing_config = payload
                .and_then(|p| match p {
                    routing_types::DynamicRoutingPayload::EliminationRoutingPayload(config) => {
                        Some(config)
                    }
                    _ => None,
                })
                .unwrap_or_else(
                    routing_types::EliminationRoutingConfig::open_router_config_default,
                );

            open_router::DecisionEngineConfigSetupRequest {
                merchant_id: profile_id.get_string_repr().to_string(),
                config: open_router::DecisionEngineConfigVariant::Elimination(
                    elimination_based_routing_config
                        .get_decision_engine_configs()
                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                            message: "Decision engine config not found".to_string(),
                        })
                        .attach_printable("Decision engine config not found")?,
                ),
            }
        }
        routing_types::DynamicRoutingType::ContractBasedRouting => {
            return Err((errors::ApiErrorResponse::InvalidRequestData {
                message: "Contract routing cannot be set as default".to_string(),
            })
            .into())
        }
    };

    // Create merchant in Decision Engine if it is not already created
    create_merchant_in_decision_engine_if_not_exists(state, profile_id, dynamic_routing_algo_ref)
        .await;

    routing_utils::ConfigApiClient::send_decision_engine_request::<_, serde_json::Value>(
        state,
        services::Method::Post,
        DECISION_ENGINE_RULE_CREATE_ENDPOINT,
        Some(decision_engine_config_request),
        None,
        None,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Unable to setup decision engine dynamic routing")?;

    Ok(())
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn update_decision_engine_dynamic_routing_setup(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    request: serde_json::Value,
    dynamic_routing_type: routing_types::DynamicRoutingType,
    dynamic_routing_algo_ref: &mut routing_types::DynamicRoutingAlgorithmRef,
) -> RouterResult<()> {
    logger::debug!(
        "performing call with open_router for profile {}",
        profile_id.get_string_repr()
    );

    let decision_engine_request = match dynamic_routing_type {
        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
            let success_rate_config: routing_types::SuccessBasedRoutingConfig = request
                .parse_value("SuccessBasedRoutingConfig")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("unable to deserialize SuccessBasedRoutingConfig")?;

            open_router::DecisionEngineConfigSetupRequest {
                merchant_id: profile_id.get_string_repr().to_string(),
                config: open_router::DecisionEngineConfigVariant::SuccessRate(
                    success_rate_config
                        .get_decision_engine_configs()
                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                            message: "Decision engine config not found".to_string(),
                        })
                        .attach_printable("Decision engine config not found")?,
                ),
            }
        }
        routing_types::DynamicRoutingType::EliminationRouting => {
            let elimination_config: routing_types::EliminationRoutingConfig = request
                .parse_value("EliminationRoutingConfig")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("unable to deserialize EliminationRoutingConfig")?;

            open_router::DecisionEngineConfigSetupRequest {
                merchant_id: profile_id.get_string_repr().to_string(),
                config: open_router::DecisionEngineConfigVariant::Elimination(
                    elimination_config
                        .get_decision_engine_configs()
                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                            message: "Decision engine config not found".to_string(),
                        })
                        .attach_printable("Decision engine config not found")?,
                ),
            }
        }
        routing_types::DynamicRoutingType::ContractBasedRouting => {
            return Err((errors::ApiErrorResponse::InvalidRequestData {
                message: "Contract routing cannot be set as default".to_string(),
            })
            .into())
        }
    };

    // Create merchant in Decision Engine if it is not already created
    create_merchant_in_decision_engine_if_not_exists(state, profile_id, dynamic_routing_algo_ref)
        .await;

    routing_utils::ConfigApiClient::send_decision_engine_request::<_, serde_json::Value>(
        state,
        services::Method::Post,
        DECISION_ENGINE_RULE_UPDATE_ENDPOINT,
        Some(decision_engine_request),
        None,
        None,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Unable to update decision engine dynamic routing")?;

    Ok(())
}

#[cfg(all(feature = "v1", feature = "dynamic_routing"))]
pub async fn get_decision_engine_active_dynamic_routing_algorithm(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    dynamic_routing_type: open_router::DecisionEngineDynamicAlgorithmType,
) -> RouterResult<Option<open_router::DecisionEngineConfigSetupRequest>> {
    logger::debug!(
        "decision_engine_euclid: GET api call for decision active {:?} routing algorithm",
        dynamic_routing_type
    );
    let request = open_router::GetDecisionEngineConfigRequest {
        merchant_id: profile_id.get_string_repr().to_owned(),
        algorithm: dynamic_routing_type,
    };
    let response: Option<open_router::DecisionEngineConfigSetupRequest> =
        routing_utils::ConfigApiClient::send_decision_engine_request(
            state,
            services::Method::Post,
            DECISION_ENGINE_RULE_GET_ENDPOINT,
            Some(request),
            None,
            None,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get active dynamic algorithm from decision engine")?
        .response;

    Ok(response)
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn disable_decision_engine_dynamic_routing_setup(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    dynamic_routing_type: routing_types::DynamicRoutingType,
    dynamic_routing_algo_ref: &mut routing_types::DynamicRoutingAlgorithmRef,
) -> RouterResult<()> {
    logger::debug!(
        "performing call with open_router for profile {}",
        profile_id.get_string_repr()
    );

    let decision_engine_request = open_router::FetchRoutingConfig {
        merchant_id: profile_id.get_string_repr().to_string(),
        algorithm: match dynamic_routing_type {
            routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
                open_router::AlgorithmType::SuccessRate
            }
            routing_types::DynamicRoutingType::EliminationRouting => {
                open_router::AlgorithmType::Elimination
            }
            routing_types::DynamicRoutingType::ContractBasedRouting => {
                return Err((errors::ApiErrorResponse::InvalidRequestData {
                    message: "Contract routing is not enabled for decision engine".to_string(),
                })
                .into())
            }
        },
    };

    // Create merchant in Decision Engine if it is not already created
    create_merchant_in_decision_engine_if_not_exists(state, profile_id, dynamic_routing_algo_ref)
        .await;

    routing_utils::ConfigApiClient::send_decision_engine_request::<_, serde_json::Value>(
        state,
        services::Method::Post,
        DECISION_ENGINE_RULE_DELETE_ENDPOINT,
        Some(decision_engine_request),
        None,
        None,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Unable to disable decision engine dynamic routing")?;

    Ok(())
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn create_merchant_in_decision_engine_if_not_exists(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    dynamic_routing_algo_ref: &mut routing_types::DynamicRoutingAlgorithmRef,
) {
    if !dynamic_routing_algo_ref.is_merchant_created_in_decision_engine {
        logger::debug!(
            "Creating merchant_account in decision engine for profile {}",
            profile_id.get_string_repr()
        );

        create_decision_engine_merchant(state, profile_id)
            .await
            .map_err(|err| {
                logger::warn!("Merchant creation error in decision_engine: {err:?}");
            })
            .ok();

        // TODO: Update the status based on the status code or error message from the API call
        dynamic_routing_algo_ref.update_merchant_creation_status_in_decision_engine(true);
    }
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn create_decision_engine_merchant(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
) -> RouterResult<()> {
    let merchant_account_req = open_router::MerchantAccount {
        merchant_id: profile_id.get_string_repr().to_string(),
        gateway_success_rate_based_decider_input: None,
    };

    routing_utils::ConfigApiClient::send_decision_engine_request::<_, serde_json::Value>(
        state,
        services::Method::Post,
        DECISION_ENGINE_MERCHANT_CREATE_ENDPOINT,
        Some(merchant_account_req),
        None,
        None,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Failed to create merchant account on decision engine")?;

    Ok(())
}

#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
#[instrument(skip_all)]
pub async fn delete_decision_engine_merchant(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
) -> RouterResult<()> {
    let path = format!(
        "{}/{}",
        DECISION_ENGINE_MERCHANT_BASE_ENDPOINT,
        profile_id.get_string_repr()
    );
    routing_utils::ConfigApiClient::send_decision_engine_request::<_, serde_json::Value>(
        state,
        services::Method::Delete,
        &path,
        None::<id_type::ProfileId>,
        None,
        None,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Failed to delete merchant account on decision engine")?;

    Ok(())
}


File: crates/hyperswitch_connectors/src/connectors/stripe/transformers/connect.rs
 Public structs: 14

use api_models;
use common_enums::{enums, Currency};
use common_utils::{ext_traits::OptionExt as _, pii::Email};
use error_stack::ResultExt;
use hyperswitch_domain_models::types::{PayoutsResponseData, PayoutsRouterData};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use super::ErrorDetails;
use crate::{
    types::{PayoutIndividualDetailsExt as _, PayoutsResponseRouterData},
    utils::{CustomerDetails as _, PayoutsData as _, RouterData},
};
type Error = error_stack::Report<errors::ConnectorError>;

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StripeConnectPayoutStatus {
    Canceled,
    Failed,
    InTransit,
    Paid,
    Pending,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct StripeConnectErrorResponse {
    pub error: ErrorDetails,
}

// Payouts
#[derive(Clone, Debug, Serialize)]
pub struct StripeConnectPayoutCreateRequest {
    amount: i64,
    currency: Currency,
    destination: String,
    transfer_group: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StripeConnectPayoutCreateResponse {
    id: String,
    description: Option<String>,
    source_transaction: Option<String>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct TransferReversals {
    object: String,
    has_more: bool,
    total_count: i32,
    url: String,
}

#[derive(Clone, Debug, Serialize)]
pub struct StripeConnectPayoutFulfillRequest {
    amount: i64,
    currency: Currency,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StripeConnectPayoutFulfillResponse {
    id: String,
    currency: String,
    description: Option<String>,
    failure_balance_transaction: Option<String>,
    failure_code: Option<String>,
    failure_message: Option<String>,
    original_payout: Option<String>,
    reversed_by: Option<String>,
    statement_descriptor: Option<String>,
    status: StripeConnectPayoutStatus,
}

#[derive(Clone, Debug, Serialize)]
pub struct StripeConnectReversalRequest {
    amount: i64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StripeConnectReversalResponse {
    id: String,
    source_refund: Option<String>,
}

#[derive(Clone, Debug, Serialize)]
pub struct StripeConnectRecipientCreateRequest {
    #[serde(rename = "type")]
    account_type: String,
    country: Option<enums::CountryAlpha2>,
    email: Option<Email>,
    #[serde(rename = "capabilities[card_payments][requested]")]
    capabilities_card_payments: Option<bool>,
    #[serde(rename = "capabilities[transfers][requested]")]
    capabilities_transfers: Option<bool>,
    #[serde(rename = "tos_acceptance[date]")]
    tos_acceptance_date: Option<i64>,
    #[serde(rename = "tos_acceptance[ip]")]
    tos_acceptance_ip: Option<Secret<String>>,
    business_type: String,
    #[serde(rename = "business_profile[mcc]")]
    business_profile_mcc: Option<i32>,
    #[serde(rename = "business_profile[url]")]
    business_profile_url: Option<String>,
    #[serde(rename = "business_profile[name]")]
    business_profile_name: Option<Secret<String>>,
    #[serde(rename = "company[name]")]
    company_name: Option<Secret<String>>,
    #[serde(rename = "company[address][line1]")]
    company_address_line1: Option<Secret<String>>,
    #[serde(rename = "company[address][line2]")]
    company_address_line2: Option<Secret<String>>,
    #[serde(rename = "company[address][postal_code]")]
    company_address_postal_code: Option<Secret<String>>,
    #[serde(rename = "company[address][city]")]
    company_address_city: Option<Secret<String>>,
    #[serde(rename = "company[address][state]")]
    company_address_state: Option<Secret<String>>,
    #[serde(rename = "company[phone]")]
    company_phone: Option<Secret<String>>,
    #[serde(rename = "company[tax_id]")]
    company_tax_id: Option<Secret<String>>,
    #[serde(rename = "company[owners_provided]")]
    company_owners_provided: Option<bool>,
    #[serde(rename = "individual[first_name]")]
    individual_first_name: Option<Secret<String>>,
    #[serde(rename = "individual[last_name]")]
    individual_last_name: Option<Secret<String>>,
    #[serde(rename = "individual[dob][day]")]
    individual_dob_day: Option<Secret<String>>,
    #[serde(rename = "individual[dob][month]")]
    individual_dob_month: Option<Secret<String>>,
    #[serde(rename = "individual[dob][year]")]
    individual_dob_year: Option<Secret<String>>,
    #[serde(rename = "individual[address][line1]")]
    individual_address_line1: Option<Secret<String>>,
    #[serde(rename = "individual[address][line2]")]
    individual_address_line2: Option<Secret<String>>,
    #[serde(rename = "individual[address][postal_code]")]
    individual_address_postal_code: Option<Secret<String>>,
    #[serde(rename = "individual[address][city]")]
    individual_address_city: Option<String>,
    #[serde(rename = "individual[address][state]")]
    individual_address_state: Option<Secret<String>>,
    #[serde(rename = "individual[email]")]
    individual_email: Option<Email>,
    #[serde(rename = "individual[phone]")]
    individual_phone: Option<Secret<String>>,
    #[serde(rename = "individual[id_number]")]
    individual_id_number: Option<Secret<String>>,
    #[serde(rename = "individual[ssn_last_4]")]
    individual_ssn_last_4: Option<Secret<String>>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct StripeConnectRecipientCreateResponse {
    id: String,
}

#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum StripeConnectRecipientAccountCreateRequest {
    Bank(RecipientBankAccountRequest),
    Card(RecipientCardAccountRequest),
    Token(RecipientTokenRequest),
}

#[derive(Clone, Debug, Serialize)]
pub struct RecipientTokenRequest {
    external_account: String,
}

#[derive(Clone, Debug, Serialize)]
pub struct RecipientCardAccountRequest {
    #[serde(rename = "external_account[object]")]
    external_account_object: String,
    #[serde(rename = "external_account[number]")]
    external_account_number: Secret<String>,
    #[serde(rename = "external_account[exp_month]")]
    external_account_exp_month: Secret<String>,
    #[serde(rename = "external_account[exp_year]")]
    external_account_exp_year: Secret<String>,
}

#[derive(Clone, Debug, Serialize)]
pub struct RecipientBankAccountRequest {
    #[serde(rename = "external_account[object]")]
    external_account_object: String,
    #[serde(rename = "external_account[country]")]
    external_account_country: enums::CountryAlpha2,
    #[serde(rename = "external_account[currency]")]
    external_account_currency: Currency,
    #[serde(rename = "external_account[account_holder_name]")]
    external_account_account_holder_name: Secret<String>,
    #[serde(rename = "external_account[account_number]")]
    external_account_account_number: Secret<String>,
    #[serde(rename = "external_account[account_holder_type]")]
    external_account_account_holder_type: String,
    #[serde(rename = "external_account[routing_number]")]
    external_account_routing_number: Secret<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StripeConnectRecipientAccountCreateResponse {
    id: String,
}

// Payouts create/transfer request transform
impl<F> TryFrom<&PayoutsRouterData<F>> for StripeConnectPayoutCreateRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let request = item.request.to_owned();
        let connector_customer_id = item.get_connector_customer_id()?;
        Ok(Self {
            amount: request.amount,
            currency: request.destination_currency,
            destination: connector_customer_id,
            transfer_group: item.connector_request_reference_id.clone(),
        })
    }
}

// Payouts create response transform
impl<F> TryFrom<PayoutsResponseRouterData<F, StripeConnectPayoutCreateResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, StripeConnectPayoutCreateResponse>,
    ) -> Result<Self, Self::Error> {
        let response: StripeConnectPayoutCreateResponse = item.response;

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(enums::PayoutStatus::RequiresFulfillment),
                connector_payout_id: Some(response.id),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Payouts fulfill request transform
impl<F> TryFrom<&PayoutsRouterData<F>> for StripeConnectPayoutFulfillRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let request = item.request.to_owned();
        Ok(Self {
            amount: request.amount,
            currency: request.destination_currency,
        })
    }
}

// Payouts fulfill response transform
impl<F> TryFrom<PayoutsResponseRouterData<F, StripeConnectPayoutFulfillResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, StripeConnectPayoutFulfillResponse>,
    ) -> Result<Self, Self::Error> {
        let response: StripeConnectPayoutFulfillResponse = item.response;

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(enums::PayoutStatus::from(response.status)),
                connector_payout_id: Some(response.id),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Payouts reversal request transform
impl<F> TryFrom<&PayoutsRouterData<F>> for StripeConnectReversalRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        Ok(Self {
            amount: item.request.amount,
        })
    }
}

// Payouts reversal response transform
impl<F> TryFrom<PayoutsResponseRouterData<F, StripeConnectReversalResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, StripeConnectReversalResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(enums::PayoutStatus::Cancelled),
                connector_payout_id: item.data.request.connector_payout_id.clone(),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Recipient creation request transform
impl<F> TryFrom<&PayoutsRouterData<F>> for StripeConnectRecipientCreateRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let request = item.request.to_owned();
        let customer_details = request.get_customer_details()?;
        let customer_email = customer_details.get_customer_email()?;
        let address = item.get_billing_address()?.clone();
        let payout_vendor_details = request.get_vendor_details()?;
        let (vendor_details, individual_details) = (
            payout_vendor_details.vendor_details,
            payout_vendor_details.individual_details,
        );
        Ok(Self {
            account_type: vendor_details.account_type,
            country: address.country,
            email: Some(customer_email.clone()),
            capabilities_card_payments: vendor_details.capabilities_card_payments,
            capabilities_transfers: vendor_details.capabilities_transfers,
            tos_acceptance_date: individual_details.tos_acceptance_date,
            tos_acceptance_ip: individual_details.tos_acceptance_ip,
            business_type: vendor_details.business_type,
            business_profile_mcc: vendor_details.business_profile_mcc,
            business_profile_url: vendor_details.business_profile_url,
            business_profile_name: vendor_details.business_profile_name.clone(),
            company_name: vendor_details.business_profile_name,
            company_address_line1: vendor_details.company_address_line1,
            company_address_line2: vendor_details.company_address_line2,
            company_address_postal_code: vendor_details.company_address_postal_code,
            company_address_city: vendor_details.company_address_city,
            company_address_state: vendor_details.company_address_state,
            company_phone: vendor_details.company_phone,
            company_tax_id: vendor_details.company_tax_id,
            company_owners_provided: vendor_details.company_owners_provided,
            individual_first_name: address.first_name,
            individual_last_name: address.last_name,
            individual_dob_day: individual_details.individual_dob_day,
            individual_dob_month: individual_details.individual_dob_month,
            individual_dob_year: individual_details.individual_dob_year,
            individual_address_line1: address.line1,
            individual_address_line2: address.line2,
            individual_address_postal_code: address.zip,
            individual_address_city: address.city,
            individual_address_state: address.state,
            individual_email: Some(customer_email),
            individual_phone: customer_details.phone,
            individual_id_number: individual_details.individual_id_number,
            individual_ssn_last_4: individual_details.individual_ssn_last_4,
        })
    }
}

// Recipient creation response transform
impl<F> TryFrom<PayoutsResponseRouterData<F, StripeConnectRecipientCreateResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, StripeConnectRecipientCreateResponse>,
    ) -> Result<Self, Self::Error> {
        let response: StripeConnectRecipientCreateResponse = item.response;
        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(enums::PayoutStatus::RequiresVendorAccountCreation),
                connector_payout_id: Some(response.id),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: true,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Recipient account's creation request
impl<F> TryFrom<&PayoutsRouterData<F>> for StripeConnectRecipientAccountCreateRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let request = item.request.to_owned();
        let payout_method_data = item.get_payout_method_data()?;
        let customer_details = request.get_customer_details()?;
        let customer_name = customer_details.get_customer_name()?;
        let payout_vendor_details = request.get_vendor_details()?;
        match payout_method_data {
            api_models::payouts::PayoutMethodData::Card(_) => {
                Ok(Self::Token(RecipientTokenRequest {
                    external_account: "tok_visa_debit".to_string(),
                }))
            }
            api_models::payouts::PayoutMethodData::Bank(bank) => match bank {
                api_models::payouts::Bank::Ach(bank_details) => {
                    Ok(Self::Bank(RecipientBankAccountRequest {
                        external_account_object: "bank_account".to_string(),
                        external_account_country: bank_details
                            .bank_country_code
                            .get_required_value("bank_country_code")
                            .change_context(errors::ConnectorError::MissingRequiredField {
                                field_name: "bank_country_code",
                            })?,
                        external_account_currency: request.destination_currency.to_owned(),
                        external_account_account_holder_name: customer_name,
                        external_account_account_holder_type: payout_vendor_details
                            .individual_details
                            .get_external_account_account_holder_type()?,
                        external_account_account_number: bank_details.bank_account_number,
                        external_account_routing_number: bank_details.bank_routing_number,
                    }))
                }
                api_models::payouts::Bank::Bacs(_) => Err(errors::ConnectorError::NotSupported {
                    message: "BACS payouts are not supported".to_string(),
                    connector: "stripe",
                }
                .into()),
                api_models::payouts::Bank::Sepa(_) => Err(errors::ConnectorError::NotSupported {
                    message: "SEPA payouts are not supported".to_string(),
                    connector: "stripe",
                }
                .into()),
                api_models::payouts::Bank::Pix(_) => Err(errors::ConnectorError::NotSupported {
                    message: "PIX payouts are not supported".to_string(),
                    connector: "stripe",
                }
                .into()),
            },
            api_models::payouts::PayoutMethodData::Wallet(_) => {
                Err(errors::ConnectorError::NotSupported {
                    message: "Payouts via wallets are not supported".to_string(),
                    connector: "stripe",
                }
                .into())
            }
        }
    }
}

// Recipient account's creation response
impl<F> TryFrom<PayoutsResponseRouterData<F, StripeConnectRecipientAccountCreateResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, StripeConnectRecipientAccountCreateResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(enums::PayoutStatus::RequiresCreation),
                connector_payout_id: item.data.request.connector_payout_id.clone(),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

impl From<StripeConnectPayoutStatus> for enums::PayoutStatus {
    fn from(stripe_connect_status: StripeConnectPayoutStatus) -> Self {
        match stripe_connect_status {
            StripeConnectPayoutStatus::Paid => Self::Success,
            StripeConnectPayoutStatus::Failed => Self::Failed,
            StripeConnectPayoutStatus::Canceled => Self::Cancelled,
            StripeConnectPayoutStatus::Pending | StripeConnectPayoutStatus::InTransit => {
                Self::Pending
            }
        }
    }
}


pub fn set_error_callback(&self, callback: tokio::sync::oneshot::Sender<()


pub struct PayoutsData {
    pub payout_id: id_type::PayoutId,
    pub amount: i64,
    pub connector_payout_id: Option<String>,
    pub destination_currency: storage_enums::Currency,
    pub source_currency: storage_enums::Currency,
    pub payout_type: Option<storage_enums::PayoutType>,
    pub entity_type: storage_enums::PayoutEntityType,
    pub customer_details: Option<CustomerDetails>,
    pub vendor_details: Option<api_models::payouts::PayoutVendorAccountDetails>,

    // New minor amount for amount framework
    pub minor_amount: MinorUnit,
    pub priority: Option<storage_enums::PayoutSendPriority>,
    pub connector_transfer_method_id: Option<String>,
}


impl api::PayoutSync for Wise {}


pub async fn list_initial_attempts_by_profile_id_constraints(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        created_after: time::PrimitiveDateTime,
        created_before: time::PrimitiveDateTime,
        limit: Option<i64>,
        offset: Option<i64>,
        event_types: HashSet<common_enums::EventType>,
        is_delivered: Option<bool>,
    ) -> StorageResult<Vec<Self>> {
        use async_bb8_diesel::AsyncRunQueryDsl;
        use diesel::{debug_query, pg::Pg, QueryDsl};
        use error_stack::ResultExt;
        use router_env::logger;

        use super::generics::db_metrics::{track_database_call, DatabaseOperation};
        use crate::errors::DatabaseError;

        let mut query = Self::table()
            .filter(
                dsl::event_id
                    .nullable()
                    .eq(dsl::initial_attempt_id) // Filter initial attempts only
                    .and(dsl::business_profile_id.eq(profile_id.to_owned())),
            )
            .order(dsl::created_at.desc())
            .into_boxed();

        query = Self::apply_filters(
            query,
            None,
            (dsl::created_at, created_after, created_before),
            limit,
            offset,
            event_types,
            is_delivered,
        );

        logger::debug!(query = %debug_query::<Pg, _>(&query).to_string());

        track_database_call::<Self, _, _>(query.get_results_async(conn), DatabaseOperation::Filter)
            .await
            .change_context(DatabaseError::Others) // Query returns empty Vec when no records are found
            .attach_printable("Error filtering events by constraints")
    }


pub struct Profile;


impl api::PaymentToken for Powertranz {}

impl api::PaymentToken for for Powertranz


impl api::RefundSync for Hyperwallet {}

impl api::RefundSync for for Hyperwallet


impl Responder {
    let flow = Flow::DecisionManagerRetrieveConfig;
    Box::pin(oss_api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, auth: auth::AuthenticationData, _, _| {
            conditional_config::retrieve_conditional_config(state, auth.key_store, auth.profile)
        },
        #[cfg(not(feature = "release"))]
        auth::auth_type(
            &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            &auth::JWTAuth {
                permission: Permission::ProfileThreeDsDecisionManagerWrite,
            },
            req.headers(),
        ),
        #[cfg(feature = "release")]
        &auth::JWTAuth {
            permission: Permission::ProfileThreeDsDecisionManagerWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct PaypalVaultResponse {
    id: String,
    status: String,
    customer: CustomerId,
}


impl api::PaymentSync for Powertranz {}

impl api::PaymentSync for for Powertranz


pub async fn set_role_info_in_cache<A>(
    state: &A,
    role_id: &str,
    role_info: &roles::RoleInfo,
    expiry: i64,
) -> RouterResult<()>
where
    A: SessionStateInfo + Sync,
{
    let redis_conn = get_redis_connection_for_global_tenant(state)?;

    redis_conn
        .serialize_and_set_key_with_expiry(
            &get_cache_key_from_role_id(role_id).into(),
            role_info,
            expiry,
        )
        .await
        .change_context(ApiErrorResponse::InternalServerError)
}


pub struct ZenRouterData<T> {
    pub amount: String,
    pub router_data: T,
}


impl Responder {
        let flow = AnalyticsFlow::GetDisputeFilters;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            json_payload.into_inner(),
            |state, auth: AuthenticationData, req, _| async move {
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let profile_id = auth
                    .profile_id
                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
                    .change_context(AnalyticsError::AccessForbiddenError)?;
                let auth: AuthInfo = AuthInfo::ProfileLevel {
                    org_id: org_id.clone(),
                    merchant_id: merchant_id.clone(),
                    profile_ids: vec![profile_id.clone()],
                };
                analytics::disputes::get_filters(&state.pool, req, &auth)
                    .await
                    .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::ProfileAnalyticsRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub struct FiuuRefundSyncRequest {
    #[serde(rename = "TxnID")]
    txn_id: String,
    #[serde(rename = "MerchantID")]
    merchant_id: Secret<String>,
    signature: Secret<String>,
}


impl api::PaymentSession for Jpmorgan {}

impl api::PaymentSession for for Jpmorgan


pub async fn response_handler(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payout_data: &PayoutData,
) -> RouterResult<payouts::PayoutCreateResponse> {
    let payout_attempt = payout_data.payout_attempt.to_owned();
    let payouts = payout_data.payouts.to_owned();

    let payout_method_id: Option<String> = payout_data.payment_method.as_ref().map(|pm| {
        #[cfg(feature = "v1")]
        {
            pm.payment_method_id.clone()
        }

        #[cfg(feature = "v2")]
        {
            pm.id.clone().get_string_repr().to_string()
        }
    });

    let payout_link = payout_data.payout_link.to_owned();
    let billing_address = payout_data.billing_address.to_owned();
    let customer_details = payout_data.customer_details.to_owned();
    let customer_id = payouts.customer_id;
    let billing = billing_address.map(From::from);

    let translated_unified_message = helpers::get_translated_unified_code_and_message(
        state,
        payout_attempt.unified_code.as_ref(),
        payout_attempt.unified_message.as_ref(),
        &payout_data.current_locale,
    )
    .await?;

    let additional_payout_method_data = payout_attempt.additional_payout_method_data.clone();

    let payout_method_data =
        additional_payout_method_data.map(payouts::PayoutMethodDataResponse::from);

    let response = api::PayoutCreateResponse {
        payout_id: payouts.payout_id.to_owned(),
        merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
        merchant_order_reference_id: payout_attempt.merchant_order_reference_id.clone(),
        amount: payouts.amount,
        currency: payouts.destination_currency.to_owned(),
        connector: payout_attempt.connector,
        payout_type: payouts.payout_type.to_owned(),
        payout_method_data,
        billing,
        auto_fulfill: payouts.auto_fulfill,
        customer_id,
        email: customer_details.as_ref().and_then(|c| c.email.clone()),
        name: customer_details.as_ref().and_then(|c| c.name.clone()),
        phone: customer_details.as_ref().and_then(|c| c.phone.clone()),
        phone_country_code: customer_details
            .as_ref()
            .and_then(|c| c.phone_country_code.clone()),
        customer: customer_details
            .as_ref()
            .map(payment_api_types::CustomerDetailsResponse::foreign_from),
        client_secret: payouts.client_secret.to_owned(),
        return_url: payouts.return_url.to_owned(),
        business_country: payout_attempt.business_country,
        business_label: payout_attempt.business_label,
        description: payouts.description.to_owned(),
        entity_type: payouts.entity_type.to_owned(),
        recurring: payouts.recurring,
        metadata: payouts.metadata,
        merchant_connector_id: payout_attempt.merchant_connector_id.to_owned(),
        status: payout_attempt.status.to_owned(),
        error_message: payout_attempt.error_message.to_owned(),
        error_code: payout_attempt.error_code,
        profile_id: payout_attempt.profile_id,
        created: Some(payouts.created_at),
        connector_transaction_id: payout_attempt.connector_payout_id,
        priority: payouts.priority,
        attempts: None,
        unified_code: payout_attempt.unified_code,
        unified_message: translated_unified_message,
        payout_link: payout_link
            .map(|payout_link| {
                url::Url::parse(payout_link.url.peek()).map(|link| PayoutLinkResponse {
                    payout_link_id: payout_link.link_id,
                    link: link.into(),
                })
            })
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to parse payout link's URL")?,
        payout_method_id,
    };

    Ok(response)
}


pub struct PaymentMethodNew {
    pub customer_id: common_utils::id_type::CustomerId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_method_id: String,
    pub payment_method: Option<storage_enums::PaymentMethod>,
    pub payment_method_type: Option<storage_enums::PaymentMethodType>,
    pub payment_method_issuer: Option<String>,
    pub payment_method_issuer_code: Option<storage_enums::PaymentMethodIssuerCode>,
    pub accepted_currency: Option<Vec<storage_enums::Currency>>,
    pub scheme: Option<String>,
    pub token: Option<String>,
    pub cardholder_name: Option<Secret<String>>,
    pub issuer_name: Option<String>,
    pub issuer_country: Option<String>,
    pub payer_country: Option<Vec<String>>,
    pub is_stored: Option<bool>,
    pub swift_code: Option<String>,
    pub direct_debit_token: Option<String>,
    pub created_at: PrimitiveDateTime,
    pub last_modified: PrimitiveDateTime,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub payment_method_data: Option<Encryption>,
    pub locker_id: Option<String>,
    pub last_used_at: PrimitiveDateTime,
    pub connector_mandate_details: Option<serde_json::Value>,
    pub customer_acceptance: Option<pii::SecretSerdeValue>,
    pub status: storage_enums::PaymentMethodStatus,
    pub network_transaction_id: Option<String>,
    pub client_secret: Option<String>,
    pub payment_method_billing_address: Option<Encryption>,
    pub updated_by: Option<String>,
    pub version: common_enums::ApiVersion,
    pub network_token_requestor_reference_id: Option<String>,
    pub network_token_locker_id: Option<String>,
    pub network_token_payment_method_data: Option<Encryption>,
}


pub async fn generate_recovery_codes(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::RecoveryCodesGenerate;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::generate_recovery_codes(state, user),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct PaymentsTaxCalculationData {
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub shipping_cost: Option<MinorUnit>,
    pub order_details: Option<Vec<OrderDetailsWithAmount>>,
    pub shipping_address: address::Address,
}


pub struct GoPayRedirection {}