commit 72ca4e80aaa7db99a741afcc4e5bdc1d8e417bda parent 32dd6c19c4c6bdfe61bcf24efe24b2b27225fed0 Author: Antoine A <> Date: Fri, 27 Sep 2024 12:35:25 +0200 Merge branch 'dev/antoine/nexus-dev' Diffstat:
137 files changed, 28307 insertions(+), 4244 deletions(-)
diff --git a/.gitignore b/.gitignore @@ -23,4 +23,4 @@ __pycache__ *.log .DS_Store *.mk -common/src/main/resources/version.txt +common/src/main/resources/version.txt +\ No newline at end of file diff --git a/bank/build.gradle b/bank/build.gradle @@ -50,6 +50,8 @@ shadowJar { exclude(dependency("io.ktor:ktor-serialization-kotlinx-json:.*")) // Postgres unix socket driver exclude(dependency("com.kohlschutter.junixsocket:junixsocket-core:.*")) + // CLI + exclude(dependency("com.github.ajalt.mordant:mordant:.*")) // Logging exclude(dependency("ch.qos.logback:logback-classic:.*")) } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -29,6 +29,7 @@ import tech.libeufin.bank.api.* import tech.libeufin.bank.cli.LibeufinBank import tech.libeufin.bank.db.Database import tech.libeufin.common.api.talerApi +import com.github.ajalt.clikt.core.main val logger: Logger = LoggerFactory.getLogger("libeufin-bank") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt @@ -298,7 +298,7 @@ data class BearerToken( val isRefreshable: Boolean, val creationTime: Instant, val expirationTime: Instant, - val login: String + val username: String ) @Serializable diff --git a/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt @@ -118,7 +118,7 @@ private fun Routing.coreBankTokenApi(db: Database, cfg: BankConfig) { } } if (!db.token.create( - login = username, + username = username, content = token.raw, creationTime = creationTime, expirationTime = expirationTimestamp, @@ -208,7 +208,7 @@ suspend fun createAccount( ) suspend fun doDb(internalPayto: Payto) = db.account.create( - login = req.username, + username = req.username, name = req.name, email = req.contact_data?.email?.get(), phone = req.contact_data?.phone?.get(), @@ -260,7 +260,7 @@ suspend fun patchAccount( db: Database, cfg: BankConfig, req: AccountReconfiguration, - login: String, + username: String, isAdmin: Boolean, is2fa: Boolean, channel: TanChannel? = null, @@ -268,13 +268,13 @@ suspend fun patchAccount( ): AccountPatchResult { req.debit_threshold?.run { cfg.checkRegionalCurrency(this) } - if (login == "admin" && req.is_public == true) + if (username == "admin" && req.is_public == true) throw conflict( "'admin' account cannot be public", TalerErrorCode.END ) - if (login == "exchange" && req.is_taler_exchange == false) + if (username == "exchange" && req.is_taler_exchange == false) throw conflict( "'exchange' account must be a taler exchange account", TalerErrorCode.END @@ -285,7 +285,7 @@ suspend fun patchAccount( } return db.account.reconfig( - login = login, + username = username, name = req.name, cashoutPayto = req.cashout_payto_uri, email = req.contact_data?.email ?: Option.None, @@ -312,7 +312,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { "Insufficient admin funds to grant bonus", TalerErrorCode.BANK_UNALLOWED_DEBIT ) - AccountCreationResult.LoginReuse -> throw conflict( + AccountCreationResult.UsernameReuse -> throw conflict( "Account username reuse '${req.username}'", TalerErrorCode.BANK_REGISTER_USERNAME_REUSE ) @@ -630,7 +630,7 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) = conditio ctx.checkFiatCurrency(req.amount_credit) val res = db.cashout.create( - login = username, + username = username, requestUid = req.request_uid, amountDebit = req.amount_debit, amountCredit = req.amount_credit, @@ -709,7 +709,7 @@ private fun Routing.coreBankTanApi(db: Database, ctx: BankConfig) { val id = call.longPath("CHALLENGE_ID") val res = db.tan.send( id = id, - login = username, + username = username, code = Tan.genCode(), timestamp = Instant.now(), retryCounter = TAN_RETRY_COUNTER, @@ -773,7 +773,7 @@ private fun Routing.coreBankTanApi(db: Database, ctx: BankConfig) { val code = req.tan.removePrefix("T-") val res = db.tan.solve( id = id, - login = username, + username = username, code = code, timestamp = Instant.now() ) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt @@ -51,7 +51,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { ctx.checkRegionalCurrency(req.amount) val res = db.exchange.transfer( req = req, - login = username, + username = username, timestamp = Instant.now() ) when (res) { @@ -160,7 +160,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { amount = amount, debitAccount = debitAccount, subject = subject, - login = username, + username = username, timestamp = timestamp, metadata = metadata ) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/auth/Tan.kt b/bank/src/main/kotlin/tech/libeufin/bank/auth/Tan.kt @@ -48,7 +48,7 @@ suspend inline fun <reified B> ApplicationCall.respondChallenge( val json = Json.encodeToString(kotlinx.serialization.serializer<B>(), body) val code = Tan.genCode() val id = db.tan.new( - login = username, + username = username, op = op, body = json, code = code, diff --git a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt @@ -30,8 +30,8 @@ import tech.libeufin.bank.TokenScope import tech.libeufin.bank.db.AccountDAO.CheckPasswordResult import tech.libeufin.bank.db.Database import tech.libeufin.common.* -import tech.libeufin.common.crypto.PwCrypto import tech.libeufin.common.api.intercept +import tech.libeufin.common.crypto.PwCrypto import java.time.Instant /** Used to store if the currently authenticated user is admin */ @@ -48,7 +48,7 @@ val ApplicationCall.username: String get() = parameters.expect("USERNAME") val PipelineContext<Unit, ApplicationCall>.username: String get() = call.username /** Check if current auth account is admin */ -val ApplicationCall.isAdmin: Boolean get() = attributes.getOrNull(AUTH_IS_ADMIN) ?: false +val ApplicationCall.isAdmin: Boolean get() = attributes.getOrNull(AUTH_IS_ADMIN) == true /** Check if current auth account is admin */ val PipelineContext<Unit, ApplicationCall>.isAdmin: Boolean get() = call.isAdmin @@ -65,18 +65,18 @@ val ApplicationCall.authToken: ByteArray? get() = attributes.getOrNull(AUTH_TOKE fun Route.authAdmin(db: Database, pwCrypto: PwCrypto, scope: TokenScope, enforce: Boolean = true, callback: Route.() -> Unit): Route = intercept(callback) { if (enforce) { - val login = context.authenticateBankRequest(db, pwCrypto, scope) - if (login != "admin") { + val username = context.authenticateBankRequest(db, pwCrypto, scope) + if (username != "admin") { throw unauthorized("Only administrator allowed") } context.attributes.put(AUTH_IS_ADMIN, true) } else { - val login = try { + val username = try { context.authenticateBankRequest(db, pwCrypto, scope) } catch (e: Exception) { null } - context.attributes.put(AUTH_IS_ADMIN, login == "admin") + context.attributes.put(AUTH_IS_ADMIN, username == "admin") } } @@ -91,16 +91,16 @@ fun Route.authAdmin(db: Database, pwCrypto: PwCrypto, scope: TokenScope, enforce **/ fun Route.auth(db: Database, pwCrypto: PwCrypto ,scope: TokenScope, allowAdmin: Boolean = false, requireAdmin: Boolean = false, callback: Route.() -> Unit): Route = intercept(callback) { - val authLogin = context.authenticateBankRequest(db, pwCrypto, scope) - if (requireAdmin && authLogin != "admin") { + val authUsername = context.authenticateBankRequest(db, pwCrypto, scope) + if (requireAdmin && authUsername != "admin") { throw unauthorized("Only administrator allowed") } else { - val hasRight = authLogin == username || (allowAdmin && authLogin == "admin") + val hasRight = authUsername == username || (allowAdmin && authUsername == "admin") if (!hasRight) { - throw unauthorized("Customer $authLogin have no right on $username account") + throw unauthorized("Customer $authUsername have no right on $username account") } } - context.attributes.put(AUTH_IS_ADMIN, authLogin == "admin") + context.attributes.put(AUTH_IS_ADMIN, authUsername == "admin") } /** @@ -108,14 +108,14 @@ fun Route.auth(db: Database, pwCrypto: PwCrypto ,scope: TokenScope, allowAdmin: * in the Authorization header. * The allowed schemes are either 'Basic' or 'Bearer'. * - * Returns the authenticated customer login. + * Returns the authenticated customer username. */ private suspend fun ApplicationCall.authenticateBankRequest(db: Database, pwCrypto: PwCrypto, requiredScope: TokenScope): String { val header = request.headers[HttpHeaders.Authorization] // Basic auth challenge if (header == null) { - response.header(HttpHeaders.WWWAuthenticate, "Basic") + response.header(HttpHeaders.WWWAuthenticate, "Basic realm=\"LibEuFin Bank\", charset=\"UTF-8\"") throw unauthorized( "Authorization header not found", TalerErrorCode.GENERIC_PARAMETER_MISSING @@ -137,18 +137,18 @@ private suspend fun ApplicationCall.authenticateBankRequest(db: Database, pwCryp /** * Performs the HTTP Basic Authentication. * - * Returns the authenticated customer login + * Returns the authenticated customer username */ private suspend fun doBasicAuth(db: Database, encoded: String, pwCrypto: PwCrypto): String { val decoded = String(encoded.decodeBase64(), Charsets.UTF_8) - val (login, plainPassword) = decoded.splitOnce(":") ?: throw badRequest( + val (username, plainPassword) = decoded.splitOnce(":") ?: throw badRequest( "Malformed Basic auth credentials found in the Authorization header", TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED ) - return when (db.account.checkPassword(login, plainPassword, pwCrypto)) { + return when (db.account.checkPassword(username, plainPassword, pwCrypto)) { CheckPasswordResult.UnknownAccount -> throw unauthorized("Unknown account") CheckPasswordResult.PasswordMismatch -> throw unauthorized("Bad password") - CheckPasswordResult.Success -> login + CheckPasswordResult.Success -> username } } @@ -164,7 +164,7 @@ fun validScope(required: TokenScope, scope: TokenScope): Boolean { /** * Performs the secret-token HTTP Bearer Authentication. * - * Returns the authenticated customer login + * Returns the authenticated customer username */ private suspend fun ApplicationCall.doTokenAuth( db: Database, @@ -196,5 +196,5 @@ private suspend fun ApplicationCall.doTokenAuth( attributes.put(AUTH_TOKEN, decoded) - return token.login + return token.username } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/BenchPwh.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/BenchPwh.kt @@ -20,17 +20,17 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig -import tech.libeufin.bank.db.AccountDAO.AccountPatchAuthResult import tech.libeufin.bank.logger -import tech.libeufin.bank.withDb import tech.libeufin.common.CommonOption import tech.libeufin.common.cliCmd import tech.libeufin.common.crypto.PwCrypto -class BenchPwh : CliktCommand("Benchmark password hashin algorithm and configuration", name = "bench-pwh") { +class BenchPwh : CliktCommand("bench-pwh") { + override fun help(context: Context) = "Benchmark password hashin algorithm and configuration" + private val common by CommonOption() override fun run() = cliCmd(logger, common.log) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/ChangePw.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/ChangePw.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig @@ -29,7 +30,9 @@ import tech.libeufin.bank.withDb import tech.libeufin.common.CommonOption import tech.libeufin.common.cliCmd -class ChangePw : CliktCommand("Change account password", name = "passwd") { +class ChangePw : CliktCommand("passwd") { + override fun help(context: Context) = "Change account password" + private val common by CommonOption() private val username by argument("username", help = "Account username") private val password by argument( diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/CreateAccount.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/CreateAccount.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.convert import com.github.ajalt.clikt.parameters.arguments.optional @@ -27,11 +28,6 @@ import com.github.ajalt.clikt.parameters.groups.OptionGroup import com.github.ajalt.clikt.parameters.groups.cooccurring import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* -import com.github.ajalt.clikt.parameters.types.* -import io.ktor.server.application.* -import io.ktor.server.http.content.* -import io.ktor.server.response.* -import io.ktor.server.routing.* import kotlinx.serialization.json.Json import tech.libeufin.bank.* import tech.libeufin.bank.api.* @@ -76,10 +72,9 @@ class CreateAccountOption: OptionGroup() { ).convert { TanChannel.valueOf(it) } } -class CreateAccount : CliktCommand( - "Create an account, returning the payto://-URI associated with it", - name = "create-account" -) { +class CreateAccount : CliktCommand("create-account") { + override fun help(context: Context) = "Create an account, returning the payto://-URI associated with it" + private val common by CommonOption() private val json by argument().convert { Json.decodeFromString<RegisterAccountRequest>(it) }.optional() private val options by CreateAccountOption().cooccurring() @@ -108,7 +103,7 @@ class CreateAccount : CliktCommand( when (val result = createAccount(db, cfg, req, true)) { AccountCreationResult.BonusBalanceInsufficient -> throw Exception("Insufficient admin funds to grant bonus") - AccountCreationResult.LoginReuse -> + AccountCreationResult.UsernameReuse -> throw Exception("Account username reuse '${req.username}'") AccountCreationResult.PayToReuse -> throw Exception("Bank internalPayToUri reuse") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/DbInit.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/DbInit.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option @@ -33,7 +34,9 @@ import tech.libeufin.common.cliCmd import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource -class DbInit : CliktCommand("Initialize the libeufin-bank database", name = "dbinit") { +class DbInit : CliktCommand("dbinit") { + override fun help(context: Context) = "Initialize the libeufin-bank database" + private val common by CommonOption() private val reset by option( "--reset", "-r", @@ -49,7 +52,7 @@ class DbInit : CliktCommand("Initialize the libeufin-bank database", name = "dbi val res = createAdminAccount(db, cfg) when (res) { AccountCreationResult.BonusBalanceInsufficient -> {} - AccountCreationResult.LoginReuse -> {} + AccountCreationResult.UsernameReuse -> {} AccountCreationResult.PayToReuse -> throw Exception("Failed to create admin's account") is AccountCreationResult.Success -> diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/EditAccount.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/EditAccount.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert @@ -31,10 +32,9 @@ import tech.libeufin.bank.db.AccountDAO.AccountPatchResult import tech.libeufin.common.* -class EditAccount : CliktCommand( - "Edit an existing account", - name = "edit-account" -) { +class EditAccount : CliktCommand("edit-account") { + override fun help(context: Context) = "Edit an existing account" + private val common by CommonOption() private val username: String by argument( "username", diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/Gc.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/Gc.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig import tech.libeufin.bank.logger @@ -28,10 +29,9 @@ import tech.libeufin.common.CommonOption import tech.libeufin.common.cliCmd import java.time.Instant -class GC : CliktCommand( - "Run garbage collection: abort expired operations and clean expired data", - name = "gc" -) { +class GC : CliktCommand("gc") { + override fun help(context: Context) = "Run garbage collection: abort expired operations and clean expired data" + private val common by CommonOption() override fun run() = cliCmd(logger, common.log) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/Serve.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/Serve.kt @@ -20,6 +20,7 @@ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig import tech.libeufin.bank.corebankWebApp @@ -32,7 +33,9 @@ import kotlin.io.path.Path import kotlin.io.path.exists import kotlin.io.path.readText -class Serve: CliktCommand("Run libeufin-bank HTTP server", name = "serve") { +class Serve: CliktCommand("serve") { + override fun help(context: Context) = "Run libeufin-bank HTTP server" + private val common by CommonOption() override fun run() = cliCmd(logger, common.log) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt @@ -30,14 +30,14 @@ class AccountDAO(private val db: Database) { /** Result status of account creation */ sealed interface AccountCreationResult { data class Success(val payto: String): AccountCreationResult - data object LoginReuse: AccountCreationResult + data object UsernameReuse: AccountCreationResult data object PayToReuse: AccountCreationResult data object BonusBalanceInsufficient: AccountCreationResult } /** Create new account */ suspend fun create( - login: String, + username: String, password: String, name: String, email: String?, @@ -62,16 +62,16 @@ class AccountDAO(private val db: Database) { AND phone IS NOT DISTINCT FROM ? AND cashout_payto IS NOT DISTINCT FROM ? AND tan_channel IS NOT DISTINCT FROM ?::tan_enum - AND (NOT ? OR internal_payto_uri=?) + AND (NOT ? OR internal_payto=?) AND is_public=? AND is_taler_exchange=? AND max_debt=(?,?)::taler_amount AND ${if (minCashout == null) "min_cashout IS NULL" else "min_cashout IS NOT DISTINCT FROM (?,?)::taler_amount"} - ,internal_payto_uri, name + ,internal_payto, name FROM customers JOIN bank_accounts ON customer_id=owning_customer_id - WHERE login=? + WHERE username=? """) { setString(1, name) setString(2, email) @@ -87,14 +87,14 @@ class AccountDAO(private val db: Database) { if (minCashout != null) { setLong(12, minCashout.value) setInt(13, minCashout.frac) - setString(14, login) + setString(14, username) } else { - setString(12, login) + setString(12, username) } oneOrNull { Pair( pwCrypto.checkpw(password, it.getString(1)).match && it.getBoolean(2), - it.getBankPayto("internal_payto_uri", "name", ctx) + it.getBankPayto("internal_payto", "name", ctx) ) } } @@ -103,7 +103,7 @@ class AccountDAO(private val db: Database) { if (idempotent.first) { AccountCreationResult.Success(idempotent.second) } else { - AccountCreationResult.LoginReuse + AccountCreationResult.UsernameReuse } } else { if (internalPayto is IbanPayto) @@ -123,7 +123,7 @@ class AccountDAO(private val db: Database) { val customerId = conn.withStatement(""" INSERT INTO customers ( - login + username ,password_hash ,name ,email @@ -134,7 +134,7 @@ class AccountDAO(private val db: Database) { RETURNING customer_id """ ) { - setString(1, login) + setString(1, username) setString(2, pwCrypto.hashpw(password)) setString(3, name) setString(4, email) @@ -146,7 +146,7 @@ class AccountDAO(private val db: Database) { conn.withStatement(""" INSERT INTO bank_accounts( - internal_payto_uri + internal_payto ,owning_customer_id ,is_public ,is_taler_exchange @@ -203,9 +203,9 @@ class AccountDAO(private val db: Database) { TanRequired } - /** Delete account [login] */ + /** Delete account [username] */ suspend fun delete( - login: String, + username: String, is2fa: Boolean ): AccountDeletionResult = db.serializable( """ @@ -216,7 +216,7 @@ class AccountDAO(private val db: Database) { FROM account_delete(?,?,?) """ ) { - setString(1, login) + setString(1, username) setLong(2, Instant.now().micros()) setBoolean(3, is2fa) one { @@ -241,9 +241,9 @@ class AccountDAO(private val db: Database) { data object Success: AccountPatchResult } - /** Change account [login] information */ + /** Change account [username] information */ suspend fun reconfig( - login: String, + username: String, name: String?, cashoutPayto: Option<IbanPayto?>, phone: Option<String?>, @@ -286,9 +286,9 @@ class AccountDAO(private val db: Database) { FROM customers JOIN bank_accounts ON customer_id=owning_customer_id - WHERE login=? AND deleted_at IS NULL + WHERE username=? AND deleted_at IS NULL """) { - setString(1, login) + setString(1, username) oneOrNull { CurrentAccount( id = it.getLong("customer_id"), @@ -416,9 +416,9 @@ class AccountDAO(private val db: Database) { Success } - /** Change account [login] password to [newPw] if current match [oldPw] */ + /** Change account [username] password to [newPw] if current match [oldPw] */ suspend fun reconfigPassword( - login: String, + username: String, newPw: String, oldPw: String?, is2fa: Boolean, @@ -426,10 +426,10 @@ class AccountDAO(private val db: Database) { ): AccountPatchAuthResult = db.serializableTransaction { conn -> val (customerId, currentPwh, tanRequired) = conn.withStatement(""" SELECT customer_id, password_hash, (NOT ? AND tan_channel IS NOT NULL) - FROM customers WHERE login=? AND deleted_at IS NULL + FROM customers WHERE username=? AND deleted_at IS NULL """) { setBoolean(1, is2fa) - setString(2, login) + setString(2, username) oneOrNull { Triple(it.getLong(1), it.getString(2), it.getBoolean(3)) } ?: return@serializableTransaction AccountPatchAuthResult.UnknownAccount @@ -457,13 +457,13 @@ class AccountDAO(private val db: Database) { Success } - /** Check password of account [login] against [pw], rehashing it if outdated */ - suspend fun checkPassword(login: String, pw: String, pwCrypto: PwCrypto): CheckPasswordResult { + /** Check password of account [username] against [pw], rehashing it if outdated */ + suspend fun checkPassword(username: String, pw: String, pwCrypto: PwCrypto): CheckPasswordResult { // Get user current password hash val info = db.serializable( - "SELECT customer_id, password_hash FROM customers WHERE login=? AND deleted_at IS NULL" + "SELECT customer_id, password_hash FROM customers WHERE username=? AND deleted_at IS NULL" ) { - setString(1, login) + setString(1, username) oneOrNull { Pair(it.getLong(1), it.getString(2)) } @@ -491,31 +491,31 @@ class AccountDAO(private val db: Database) { return CheckPasswordResult.Success } - /** Get bank info of account [login] */ - suspend fun bankInfo(login: String, ctx: BankPaytoCtx): BankInfo? = db.serializable( + /** Get bank info of account [username] */ + suspend fun bankInfo(username: String, ctx: BankPaytoCtx): BankInfo? = db.serializable( """ SELECT bank_account_id - ,internal_payto_uri + ,internal_payto ,name ,is_taler_exchange FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login=? + WHERE username=? """ ) { - setString(1, login) + setString(1, username) oneOrNull { BankInfo( - payto = it.getBankPayto("internal_payto_uri", "name", ctx), + payto = it.getBankPayto("internal_payto", "name", ctx), isTalerExchange = it.getBoolean("is_taler_exchange"), bankAccountId = it.getLong("bank_account_id") ) } } - /** Get data of account [login] */ - suspend fun get(login: String, ctx: BankPaytoCtx): AccountData? = db.serializable( + /** Get data of account [username] */ + suspend fun get(username: String, ctx: BankPaytoCtx): AccountData? = db.serializable( """ SELECT name @@ -523,7 +523,7 @@ class AccountDAO(private val db: Database) { ,phone ,tan_channel ,cashout_payto - ,internal_payto_uri + ,internal_payto ,(balance).val AS balance_val ,(balance).frac AS balance_frac ,has_debt @@ -540,10 +540,10 @@ class AccountDAO(private val db: Database) { FROM customers JOIN bank_accounts ON customer_id=owning_customer_id - WHERE login=? + WHERE username=? """ ) { - setString(1, login) + setString(1, username) oneOrNull { AccountData( name = it.getString("name"), @@ -553,7 +553,7 @@ class AccountDAO(private val db: Database) { ), tan_channel = it.getOptEnum<TanChannel>("tan_channel"), cashout_payto_uri = it.getString("cashout_payto"), - payto_uri = it.getBankPayto("internal_payto_uri", "name", ctx), + payto_uri = it.getBankPayto("internal_payto", "name", ctx), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), credit_debit_indicator = @@ -582,20 +582,20 @@ class AccountDAO(private val db: Database) { (balance).val AS balance_val, (balance).frac AS balance_frac, has_debt, - internal_payto_uri, - login, + internal_payto, + username, is_taler_exchange, name, bank_account_id FROM bank_accounts JOIN customers ON owning_customer_id = customer_id WHERE is_public=true AND - ${if (params.loginFilter != null) "name LIKE ? AND" else ""} + ${if (params.usernameFilter != null) "name LIKE ? AND" else ""} deleted_at IS NULL AND """, { - if (params.loginFilter != null) { - setString(1, params.loginFilter) + if (params.usernameFilter != null) { + setString(1, params.usernameFilter) 1 } else { 0 @@ -603,9 +603,9 @@ class AccountDAO(private val db: Database) { } ) { PublicAccount( - username = it.getString("login"), + username = it.getString("username"), row_id = it.getLong("bank_account_id"), - payto_uri = it.getBankPayto("internal_payto_uri", "name", ctx), + payto_uri = it.getBankPayto("internal_payto", "name", ctx), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), credit_debit_indicator = if (it.getBoolean("has_debt")) { @@ -625,7 +625,7 @@ class AccountDAO(private val db: Database) { "bank_account_id", """ SELECT - login, + username, name, (balance).val AS balance_val, (balance).frac AS balance_frac, @@ -636,7 +636,7 @@ class AccountDAO(private val db: Database) { ,(min_cashout).frac AS min_cashout_frac ,is_public ,is_taler_exchange - ,internal_payto_uri + ,internal_payto ,bank_account_id ,CASE WHEN deleted_at IS NOT NULL THEN 'deleted' @@ -644,11 +644,11 @@ class AccountDAO(private val db: Database) { END as status FROM bank_accounts JOIN customers ON owning_customer_id = customer_id - WHERE ${if (params.loginFilter != null) "name LIKE ? AND" else ""} + WHERE ${if (params.usernameFilter != null) "name LIKE ? AND" else ""} """, { - if (params.loginFilter != null) { - setString(1, params.loginFilter) + if (params.usernameFilter != null) { + setString(1, params.usernameFilter) 1 } else { 0 @@ -656,7 +656,7 @@ class AccountDAO(private val db: Database) { } ) { AccountMinimalData( - username = it.getString("login"), + username = it.getString("username"), row_id = it.getLong("bank_account_id"), name = it.getString("name"), balance = Balance( @@ -671,7 +671,7 @@ class AccountDAO(private val db: Database) { min_cashout = it.getOptAmount("min_cashout", db.bankCurrency), is_public = it.getBoolean("is_public"), is_taler_exchange = it.getBoolean("is_taler_exchange"), - payto_uri = it.getBankPayto("internal_payto_uri", "name", ctx), + payto_uri = it.getBankPayto("internal_payto", "name", ctx), status = it.getEnum("status") ) } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt @@ -41,7 +41,7 @@ class CashoutDAO(private val db: Database) { /** Create a new cashout operation */ suspend fun create( - login: String, + username: String, requestUid: ShortHashCode, amountDebit: TalerAmount, amountCredit: TalerAmount, @@ -63,7 +63,7 @@ class CashoutDAO(private val db: Database) { FROM cashout_create(?,?,(?,?)::taler_amount,(?,?)::taler_amount,?,?,?) """ ) { - setString(1, login) + setString(1, username) setBytes(2, requestUid.raw) setLong(3, amountDebit.value) setInt(4, amountDebit.frac) @@ -87,8 +87,8 @@ class CashoutDAO(private val db: Database) { } } - /** Get status of cashout operation [id] owned by [login] */ - suspend fun get(id: Long, login: String): CashoutStatusResponse? = db.serializable( + /** Get status of cashout operation [id] owned by [username] */ + suspend fun get(id: Long, username: String): CashoutStatusResponse? = db.serializable( """ SELECT (amount_debit).val as amount_debit_val @@ -107,11 +107,11 @@ class CashoutDAO(private val db: Database) { JOIN bank_accounts ON bank_account=bank_account_id JOIN customers ON owning_customer_id=customer_id LEFT JOIN bank_account_transactions ON local_transaction=bank_transaction_id - WHERE cashout_id=? AND login=? + WHERE cashout_id=? AND username=? """ ) { setLong(1, id) - setString(2, login) + setString(2, username) oneOrNull { CashoutStatusResponse( status = CashoutStatus.confirmed, @@ -132,7 +132,7 @@ class CashoutDAO(private val db: Database) { /** Get a page of all cashout operations */ suspend fun pageAll(params: PageParams): List<GlobalCashoutInfo> = db.page(params, "cashout_id", """ - SELECT cashout_id, login + SELECT cashout_id, username FROM cashout_operations JOIN bank_accounts ON bank_account=bank_account_id JOIN customers ON owning_customer_id=customer_id @@ -140,24 +140,24 @@ class CashoutDAO(private val db: Database) { """) { GlobalCashoutInfo( cashout_id = it.getLong("cashout_id"), - username = it.getString("login"), + username = it.getString("username"), status = CashoutStatus.confirmed ) } - /** Get a page of all cashout operations owned by [login] */ - suspend fun pageForUser(params: PageParams, login: String): List<CashoutInfo> = + /** Get a page of all cashout operations owned by [username] */ + suspend fun pageForUser(params: PageParams, username: String): List<CashoutInfo> = db.page(params, "cashout_id", """ SELECT cashout_id FROM cashout_operations WHERE bank_account=( SELECT bank_account_id FROM bank_accounts JOIN customers ON owning_customer_id=customer_id - WHERE deleted_at IS NULL AND login = ? + WHERE deleted_at IS NULL AND username = ? ) AND """, bind = { - setString(1, login) + setString(1, username) 1 } ) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt @@ -19,7 +19,6 @@ package tech.libeufin.bank.db -import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant @@ -38,7 +37,7 @@ class ExchangeDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,type ,reserve_pub @@ -54,14 +53,14 @@ class ExchangeDAO(private val db: Database) { row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getBankPayto("debtor_payto_uri", "debtor_name", ctx), + debit_account = it.getBankPayto("debtor_payto", "debtor_name", ctx), reserve_pub = EddsaPublicKey(it.getBytes("reserve_pub")), ) TalerIncomingType.kyc -> IncomingKycAuthTransaction( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getBankPayto("debtor_payto_uri", "debtor_name", ctx), + debit_account = it.getBankPayto("debtor_payto", "debtor_name", ctx), account_pub = EddsaPublicKey(it.getBytes("account_pub")), ) TalerIncomingType.wad -> throw UnsupportedOperationException() @@ -80,7 +79,7 @@ class ExchangeDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,creditor_payto_uri + ,creditor_payto ,creditor_name ,wtid ,exchange_base_url @@ -93,7 +92,7 @@ class ExchangeDAO(private val db: Database) { row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), - credit_account = it.getBankPayto("creditor_payto_uri", "creditor_name", ctx), + credit_account = it.getBankPayto("creditor_payto", "creditor_name", ctx), wtid = ShortHashCode(it.getBytes("wtid")), exchange_base_url = it.getString("exchange_base_url") ) @@ -114,7 +113,7 @@ class ExchangeDAO(private val db: Database) { /** Perform a Taler transfer */ suspend fun transfer( req: TransferRequest, - login: String, + username: String, timestamp: Instant ): TransferResult = db.serializable( """ @@ -144,7 +143,7 @@ class ExchangeDAO(private val db: Database) { setInt(5, req.amount.frac) setString(6, req.exchange_base_url.url) setString(7, req.credit_account.canonical) - setString(8, login) + setString(8, username) setLong(9, timestamp.micros()) one { @@ -176,7 +175,7 @@ class ExchangeDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,creditor_payto_uri + ,creditor_payto ,creditor_name FROM taler_exchange_outgoing JOIN bank_account_transactions ON bank_transaction=bank_transaction_id @@ -192,7 +191,7 @@ class ExchangeDAO(private val db: Database) { amount = it.getAmount("amount", db.bankCurrency), origin_exchange_url = it.getString("exchange_base_url"), wtid = ShortHashCode(it.getBytes("wtid")), - credit_account = it.getBankPayto("creditor_payto_uri", "creditor_name", ctx), + credit_account = it.getBankPayto("creditor_payto", "creditor_name", ctx), timestamp = it.getTalerTimestamp("transaction_date"), ) } @@ -212,7 +211,7 @@ class ExchangeDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,creditor_payto_uri + ,creditor_payto ,creditor_name FROM taler_exchange_outgoing JOIN bank_account_transactions ON bank_transaction=bank_transaction_id @@ -227,7 +226,7 @@ class ExchangeDAO(private val db: Database) { row_id = it.getLong("bank_transaction_id"), status = TransferStatusState.success, amount = it.getAmount("amount", db.bankCurrency), - credit_account = it.getBankPayto("creditor_payto_uri", "creditor_name", ctx), + credit_account = it.getBankPayto("creditor_payto", "creditor_name", ctx), timestamp = it.getTalerTimestamp("transaction_date"), ) } @@ -249,7 +248,7 @@ class ExchangeDAO(private val db: Database) { amount: TalerAmount, debitAccount: Payto, subject: String, - login: String, + username: String, timestamp: Instant, metadata: TalerIncomingMetadata ): AddIncomingResult = db.serializable( @@ -275,7 +274,7 @@ class ExchangeDAO(private val db: Database) { setLong(3, amount.value) setInt(4, amount.frac) setString(5, debitAccount.canonical) - setString(6, login) + setString(6, username) setLong(7, timestamp.micros()) setString(8, metadata.type.name) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt @@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit class TanDAO(private val db: Database) { /** Create new TAN challenge */ suspend fun new( - login: String, + username: String, op: Operation, body: String, code: String, @@ -50,7 +50,7 @@ class TanDAO(private val db: Database) { setLong(4, timestamp.micros()) setLong(5, TimeUnit.MICROSECONDS.convert(validityPeriod)) setInt(6, retryCounter) - setString(7, login) + setString(7, username) setString(8, channel?.name) setString(9, info) oneOrNull { @@ -67,7 +67,7 @@ class TanDAO(private val db: Database) { /** Request TAN challenge transmission */ suspend fun send( id: Long, - login: String, + username: String, code: String, timestamp: Instant, retryCounter: Int, @@ -76,7 +76,7 @@ class TanDAO(private val db: Database) { "SELECT out_no_op, out_tan_code, out_tan_channel, out_tan_info FROM tan_challenge_send(?,?,?,?,?,?)" ) { setLong(1, id) - setString(2, login) + setString(2, username) setString(3, code) setLong(4, timestamp.micros()) setLong(5, TimeUnit.MICROSECONDS.convert(validityPeriod)) @@ -119,7 +119,7 @@ class TanDAO(private val db: Database) { /** Solve TAN challenge */ suspend fun solve( id: Long, - login: String, + username: String, code: String, timestamp: Instant ) = db.serializable( @@ -131,7 +131,7 @@ class TanDAO(private val db: Database) { """ ) { setLong(1, id) - setString(2, login) + setString(2, username) setString(3, code) setLong(4, timestamp.micros()) one { @@ -156,22 +156,22 @@ class TanDAO(private val db: Database) { val info: String? ) - /** Get a solved TAN challenge [id] for account [login] and [op] */ + /** Get a solved TAN challenge [id] for account [username] and [op] */ suspend fun challenge( id: Long, - login: String, + username: String, op: Operation ) = db.serializable( """ SELECT body, tan_challenges.tan_channel, tan_info FROM tan_challenges JOIN customers ON customer=customer_id - WHERE challenge_id=? AND op=?::op_enum AND login=? AND deleted_at IS NULL + WHERE challenge_id=? AND op=?::op_enum AND username=? AND deleted_at IS NULL """ ) { setLong(1, id) setString(2, op.name) - setString(3, login) + setString(3, username) oneOrNull { Challenge( body = it.getString("body"), diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt @@ -30,9 +30,9 @@ import java.time.Instant /** Data access logic for auth tokens */ class TokenDAO(private val db: Database) { - /** Create new token for [login] */ + /** Create new token for [username] */ suspend fun create( - login: String, + username: String, content: ByteArray, creationTime: Instant, expirationTime: Instant, @@ -52,7 +52,7 @@ class TokenDAO(private val db: Database) { last_access ) VALUES ( ?,?,?,?::token_scope_enum, - (SELECT customer_id FROM customers WHERE login=? AND deleted_at IS NULL), + (SELECT customer_id FROM customers WHERE username=? AND deleted_at IS NULL), ?,?,? ) """ @@ -61,7 +61,7 @@ class TokenDAO(private val db: Database) { setLong(2, creationTime.micros()) setLong(3, expirationTime.micros()) setString(4, scope.name) - setString(5, login) + setString(5, username) setBoolean(6, isRefreshable) setString(7, description) setLong(8, creationTime.micros()) @@ -78,7 +78,7 @@ class TokenDAO(private val db: Database) { RETURNING creation_time, expiration_time, - login, + username, scope, is_refreshable """ @@ -89,7 +89,7 @@ class TokenDAO(private val db: Database) { BearerToken( creationTime = it.getLong("creation_time").asInstant(), expirationTime = it.getLong("expiration_time").asInstant(), - login = it.getString("login"), + username = it.getString("username"), scope = it.getEnum("scope"), isRefreshable = it.getBoolean("is_refreshable") ) @@ -104,8 +104,8 @@ class TokenDAO(private val db: Database) { execute() } - /** Get a page of all tokens of [login] accounts */ - suspend fun page(params: PageParams, login: String): List<TokenInfo> + /** Get a page of all tokens of [username] accounts */ + suspend fun page(params: PageParams, username: String): List<TokenInfo> = db.page( params, "bearer_token_id", @@ -120,11 +120,11 @@ class TokenDAO(private val db: Database) { bearer_token_id FROM bearer_tokens WHERE - bank_customer=(SELECT customer_id FROM customers WHERE deleted_at IS NULL AND login = ?) + bank_customer=(SELECT customer_id FROM customers WHERE deleted_at IS NULL AND username = ?) AND """, { - setString(1, login) + setString(1, username) 1 } ) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt @@ -22,11 +22,10 @@ package tech.libeufin.bank.db import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.bank.BankAccountTransactionInfo -import tech.libeufin.bank.TransactionDirection import tech.libeufin.common.* import tech.libeufin.common.db.* -import java.time.Instant import java.sql.Types +import java.time.Instant private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-tx-dao") @@ -170,13 +169,13 @@ class TransactionDAO(private val db: Database) { } } - /** Get transaction [rowId] owned by [login] */ - suspend fun get(rowId: Long, login: String, ctx: BankPaytoCtx): BankAccountTransactionInfo? = db.serializable( + /** Get transaction [rowId] owned by [username] */ + suspend fun get(rowId: Long, username: String, ctx: BankPaytoCtx): BankAccountTransactionInfo? = db.serializable( """ SELECT - creditor_payto_uri + creditor_payto ,creditor_name - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,subject ,(amount).val AS amount_val @@ -187,15 +186,15 @@ class TransactionDAO(private val db: Database) { FROM bank_account_transactions JOIN bank_accounts ON bank_account_transactions.bank_account_id=bank_accounts.bank_account_id JOIN customers ON customer_id=owning_customer_id - WHERE bank_transaction_id=? AND login=? + WHERE bank_transaction_id=? AND username=? """ ) { setLong(1, rowId) - setString(2, login) + setString(2, username) oneOrNull { BankAccountTransactionInfo( - creditor_payto_uri = it.getBankPayto("creditor_payto_uri", "creditor_name", ctx), - debtor_payto_uri = it.getBankPayto("debtor_payto_uri", "debtor_name", ctx), + creditor_payto_uri = it.getBankPayto("creditor_payto", "creditor_name", ctx), + debtor_payto_uri = it.getBankPayto("debtor_payto", "debtor_name", ctx), amount = it.getAmount("amount", db.bankCurrency), direction = it.getEnum("direction"), subject = it.getString("subject"), @@ -217,9 +216,9 @@ class TransactionDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,debtor_payto_uri + ,debtor_payto ,debtor_name - ,creditor_payto_uri + ,creditor_payto ,creditor_name ,subject ,direction @@ -228,8 +227,8 @@ class TransactionDAO(private val db: Database) { BankAccountTransactionInfo( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), - creditor_payto_uri = it.getBankPayto("creditor_payto_uri", "creditor_name", ctx), - debtor_payto_uri = it.getBankPayto("debtor_payto_uri", "debtor_name", ctx), + creditor_payto_uri = it.getBankPayto("creditor_payto", "creditor_name", ctx), + debtor_payto_uri = it.getBankPayto("debtor_payto", "debtor_name", ctx), amount = it.getAmount("amount", db.bankCurrency), subject = it.getString("subject"), direction = it.getEnum("direction") @@ -249,7 +248,7 @@ class TransactionDAO(private val db: Database) { ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,subject FROM bank_account_transactions WHERE direction='credit' AND @@ -258,7 +257,7 @@ class TransactionDAO(private val db: Database) { row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getBankPayto("debtor_payto_uri", "debtor_name", ctx), + debit_account = it.getBankPayto("debtor_payto", "debtor_name", ctx), subject = it.getString("subject") ) } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt @@ -45,7 +45,7 @@ class WithdrawalDAO(private val db: Database) { /** Create a new withdrawal operation */ suspend fun create( - login: String, + username: String, uuid: UUID, amount: TalerAmount?, suggested_amount: TalerAmount?, @@ -68,7 +68,7 @@ class WithdrawalDAO(private val db: Database) { ); """ ) { - setString(1, login) + setString(1, username) setObject(2, uuid) var id = 3 if (amount != null) { @@ -207,7 +207,7 @@ class WithdrawalDAO(private val db: Database) { /** Confirm withdrawal operation [uuid] */ suspend fun confirm( - login: String, + username: String, uuid: UUID, timestamp: Instant, is2fa: Boolean, @@ -227,7 +227,7 @@ class WithdrawalDAO(private val db: Database) { FROM confirm_taler_withdrawal(?,?,?,?,(?,?)::taler_amount,(?,?)::taler_amount,(?,?)::taler_amount); """ ) { - setString(1, login) + setString(1, username) setObject(2, uuid) setLong(3, timestamp.micros()) setBoolean(4, is2fa) @@ -254,7 +254,7 @@ class WithdrawalDAO(private val db: Database) { /** Get withdrawal operation [uuid] linked account username */ suspend fun getUsername(uuid: UUID): String? = db.serializable( """ - SELECT login + SELECT username FROM taler_withdrawal_operations JOIN bank_accounts ON wallet_bank_account=bank_account_id JOIN customers ON customer_id=owning_customer_id @@ -318,7 +318,7 @@ class WithdrawalDAO(private val db: Database) { ,confirmation_done ,reserve_pub ,selected_exchange_payto - ,login + ,username FROM taler_withdrawal_operations JOIN bank_accounts ON wallet_bank_account=bank_account_id JOIN customers ON customer_id=owning_customer_id @@ -331,7 +331,7 @@ class WithdrawalDAO(private val db: Database) { status = it.getEnum("status"), amount = it.getOptAmount("amount", db.bankCurrency), suggested_amount = it.getOptAmount("suggested_amount", db.bankCurrency), - username = it.getString("login"), + username = it.getString("username"), selected_exchange_account = it.getString("selected_exchange_payto"), selected_reserve_pub = it.getBytes("reserve_pub")?.run(::EddsaPublicKey) ) @@ -363,7 +363,7 @@ class WithdrawalDAO(private val db: Database) { ,selection_done ,aborted ,confirmation_done - ,internal_payto_uri + ,internal_payto ,reserve_pub ,selected_exchange_payto ,(max_amount).val as max_amount_val @@ -386,7 +386,7 @@ class WithdrawalDAO(private val db: Database) { selection_done = it.getBoolean("selection_done"), transfer_done = it.getBoolean("confirmation_done"), aborted = it.getBoolean("aborted"), - sender_wire = it.getString("internal_payto_uri"), + sender_wire = it.getString("internal_payto"), confirm_transfer_url = null, suggested_exchange = null, selected_exchange_account = it.getString("selected_exchange_payto"), diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -96,7 +96,7 @@ suspend fun createAdminAccount(db: Database, cfg: BankConfig, pw: String? = null } return db.account.create( - login = "admin", + username = "admin", password = pwStr, name = "Bank administrator", internalPayto = payto, diff --git a/bank/src/main/kotlin/tech/libeufin/bank/params.kt b/bank/src/main/kotlin/tech/libeufin/bank/params.kt @@ -83,12 +83,12 @@ data class MonitorParams( } data class AccountParams( - val page: PageParams, val loginFilter: String? + val page: PageParams, val usernameFilter: String? ) { companion object { fun extract(params: Parameters): AccountParams { - val loginFilter = params["filter_name"]?.run { "%$this%" } - return AccountParams(PageParams.extract(params), loginFilter) + val usernameFilter = params["filter_name"]?.run { "%$this%" } + return AccountParams(PageParams.extract(params), usernameFilter) } } } diff --git a/bank/src/test/kotlin/AmountTest.kt b/bank/src/test/kotlin/AmountTest.kt @@ -19,25 +19,21 @@ import io.ktor.http.* import org.junit.Test -import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult -import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult import tech.libeufin.common.* import tech.libeufin.common.db.* -import java.time.Instant -import java.util.* import kotlin.test.assertEquals class AmountTest { // Test amount computation in db @Test fun computationTest() = bankSetup { db -> db.conn { conn -> - conn.execSQLUpdate("UPDATE libeufin_bank.bank_accounts SET balance.val = 100000 WHERE internal_payto_uri = '${customerPayto.canonical}'") + conn.execSQLUpdate("UPDATE libeufin_bank.bank_accounts SET balance.val = 100000 WHERE internal_payto = '${customerPayto.canonical}'") val stmt = conn.prepareStatement(""" UPDATE libeufin_bank.bank_accounts SET balance = (?, ?)::taler_amount ,has_debt = ? ,max_debt = (?, ?)::taler_amount - WHERE internal_payto_uri = '${merchantPayto.canonical}' + WHERE internal_payto = '${merchantPayto.canonical}' """) suspend fun routine( balance: TalerAmount, diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -40,7 +40,7 @@ class CoreBankSecurityTest { fun passwordUpdate() = bankSetup { db -> suspend fun currentHash(): String { return db.serializable( - "SELECT password_hash FROM customers WHERE login='customer'" + "SELECT password_hash FROM customers WHERE username='customer'" ) { one { it.getString(1) @@ -53,7 +53,7 @@ class CoreBankSecurityTest { val pwh = CryptoUtil.hashStringSHA256(password).encodeBase64() val hash = "sha256\$$pwh" db.serializable( - "UPDATE customers SET password_hash=? WHERE login='customer'" + "UPDATE customers SET password_hash=? WHERE username='customer'" ) { setString(1, hash) executeUpdate() @@ -406,7 +406,7 @@ class CoreBankAccountsApiTest { } }.assertConflict(TalerErrorCode.END) - // Testing login conflict + // Testing username conflict client.post("/accounts") { json(req) { "name" to "Foo" @@ -611,7 +611,7 @@ class CoreBankAccountsApiTest { } }.assertOkJson<CashoutResponse>().cashout_id fillTanInfo("customer") - val tan_id = client.postA("/accounts/customer/transactions") { + client.postA("/accounts/customer/transactions") { json { "payto_uri" to "$exchangePayto?message=payout" "amount" to "KUDOS:0.3" @@ -625,7 +625,7 @@ class CoreBankAccountsApiTest { .assertChallenge() .assertNoContent() - // Check account can no longer login + // Check account can no longer username client.delete("/accounts/customer/token") { headers[HttpHeaders.Authorization] = "Bearer $token" }.assertUnauthorized() diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt @@ -45,7 +45,7 @@ class DatabaseTest { // Create admin account assertIs<AccountCreationResult.Success>(createAdminAccount(db, ctx)) // Checking idempotency - assertEquals(AccountCreationResult.LoginReuse, createAdminAccount(db, ctx)) + assertEquals(AccountCreationResult.UsernameReuse, createAdminAccount(db, ctx)) } @Test @@ -72,7 +72,7 @@ class DatabaseTest { while (true) { val result = client.postA("/accounts/customer/transactions") { json { - "payto_uri" to "$merchantPayto?message=${"concurrent 0$it".encodeURLQueryComponent()}&amount=KUDOS:0.0$it" + "payto_uri" to "$merchantPayto?message=${"concurrent 0$it".encodeURLParameter()}&amount=KUDOS:0.0$it" } } if (result.status == HttpStatusCode.InternalServerError) { diff --git a/bank/src/test/kotlin/GcTest.kt b/bank/src/test/kotlin/GcTest.kt @@ -64,7 +64,7 @@ class GcTest { // Create test accounts val payto = IbanPayto.rand() - val oldPayto = client.post("/accounts") { + client.post("/accounts") { json { "username" to "old_account" "password" to "old_account-password" @@ -72,7 +72,7 @@ class GcTest { "cashout_payto_uri" to payto } }.assertOkJson<RegisterAccountResponse>().internal_payto_uri - val recentPayto = client.post("/accounts") { + client.post("/accounts") { json { "username" to "recent_account" "password" to "recent_account-password" diff --git a/bank/src/test/kotlin/bench.kt b/bank/src/test/kotlin/bench.kt @@ -23,18 +23,13 @@ import org.junit.Test import org.postgresql.jdbc.PgConnection import tech.libeufin.bank.* import tech.libeufin.common.* -import tech.libeufin.common.test.* import tech.libeufin.common.crypto.PwCrypto +import tech.libeufin.common.test.* import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId import java.util.* import kotlin.math.max -import kotlin.math.pow -import kotlin.math.sqrt -import kotlin.time.DurationUnit -import kotlin.time.measureTime -import kotlin.time.toDuration class Bench { @@ -56,10 +51,10 @@ class Bench { val token64 = ByteArray(64) conn.genData(amount, sequenceOf( - "customers(login, name, password_hash, cashout_payto)" to { + "customers(username, name, password_hash, cashout_payto)" to { "account_$it\t$password\tMr n°$it\t$unknownPayto\n" }, - "bank_accounts(internal_payto_uri, owning_customer_id, is_public)" to { + "bank_accounts(internal_payto, owning_customer_id, is_public)" to { "payto://x-taler-bank/localhost/account_$it\t${it+skipAccount}\t${it%3==0}\n" }, "bearer_tokens(content, creation_time, expiration_time, scope, is_refreshable, bank_customer, description, last_access)" to { @@ -67,7 +62,7 @@ class Bench { val hex = token32.rand().encodeHex() "\\\\x$hex\t0\t0\treadonly\tfalse\t$account\t\\N\t0\n" }, - "bank_account_transactions(creditor_payto_uri, creditor_name, debtor_payto_uri, debtor_name, subject, amount, transaction_date, direction, bank_account_id)" to { + "bank_account_transactions(creditor_payto, creditor_name, debtor_payto, debtor_name, subject, amount, transaction_date, direction, bank_account_id)" to { val account = if (it > mid) customerAccount else it+4 "$unknownPayto\tcreditor_name\t$unknownPayto\tdebtor_name\tsubject\t(42,0)\t0\tcredit\t$exchangeAccount\n" + "$unknownPayto\tcreditor_name\t$unknownPayto\tdebtor_name\tsubject\t(42,0)\t0\tdebit\t$account\n" @@ -135,7 +130,7 @@ class Bench { client.get("/config").assertOk() // Accounts - val paytos = measureAction("account_create") { + measureAction("account_create") { client.post("/accounts") { json { "username" to "account_bench_$it" @@ -260,7 +255,7 @@ class Bench { } // Cashout - val converted = convert("KUDOS:0.1") + convert("KUDOS:0.1") val cashouts = measureAction("cashout_create") { client.postA("/accounts/customer/cashouts") { json { @@ -342,7 +337,7 @@ class Bench { // Other measureAction("monitor") { - val uuid = client.get("/monitor") { + client.get("/monitor") { pwAuth("admin") }.assertOk() } diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt @@ -81,7 +81,7 @@ fun bankSetup( // Creating the exchange and merchant accounts first. val bonus = TalerAmount.zero("KUDOS") assertIs<AccountCreationResult.Success>(db.account.create( - login = "merchant", + username = "merchant", password = "merchant-password", name = "Merchant", internalPayto = merchantPayto, @@ -99,7 +99,7 @@ fun bankSetup( pwCrypto = cfg.pwCrypto )) assertIs<AccountCreationResult.Success>(db.account.create( - login = "exchange", + username = "exchange", password = "exchange-password", name = "Exchange", internalPayto = exchangePayto, @@ -117,7 +117,7 @@ fun bankSetup( pwCrypto = cfg.pwCrypto )) assertIs<AccountCreationResult.Success>(db.account.create( - login = "customer", + username = "customer", password = "customer-password", name = "Customer", internalPayto = customerPayto, @@ -201,7 +201,7 @@ suspend fun ApplicationTestBuilder.tanInfo(account: String): Pair<TanChannel?, S suspend fun ApplicationTestBuilder.tx(from: String, amount: String, to: String, subject: String = "payout"): Long { return client.postA("/accounts/$from/transactions") { json { - "payto_uri" to "${paytos[to] ?: tmpPayTo}?message=${subject.encodeURLQueryComponent()}&amount=$amount" + "payto_uri" to "${paytos[to] ?: tmpPayTo}?message=${subject.encodeURLParameter()}&amount=$amount" } }.maybeChallenge().assertOkJson<TransactionCreateResponse>().row_id } @@ -409,8 +409,8 @@ fun HttpRequestBuilder.pwAuth(username: String? = null) { basicAuth("admin", "admin-password") } else if (url.pathSegments[1] == "accounts") { // Extract username from path - val login = url.pathSegments[2] - basicAuth(login, "$login-password") + val username = url.pathSegments[2] + basicAuth(username, "$username-password") } } diff --git a/build.gradle b/build.gradle @@ -21,11 +21,11 @@ allprojects { ext { set("kotlin_version", "2.0.20") set("ktor_version", "2.3.12") - set("clikt_version", "4.4.0") - set("coroutines_version", "1.8.1") - set("postgres_version", "42.7.4") + set("clikt_version", "5.0.0") + set("coroutines_version", "1.9.0") + set("postgres_version", "42.7.3") set("junixsocket_version", "2.10.0") - set("shadow_version", "8.3.0") + set("shadow_version", "8.3.1") } repositories { diff --git a/common/build.gradle b/common/build.gradle @@ -16,7 +16,8 @@ compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { - implementation("ch.qos.logback:logback-classic:1.5.6") + implementation("ch.qos.logback:logback-classic:1.5.8") + implementation("org.slf4j:slf4j-api:2.0.16") // Crypto implementation("org.bouncycastle:bcprov-jdk18on:1.78.1") implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1") diff --git a/common/src/main/kotlin/Cli.kt b/common/src/main/kotlin/Cli.kt @@ -20,6 +20,7 @@ package tech.libeufin.common import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.argument @@ -75,15 +76,19 @@ class CommonOption: OptionGroup() { ).enum<Level>().default(Level.INFO) } -class CliConfigCmd(configSource: ConfigSource) : CliktCommand("Inspect or change the configuration", name = "config") { +class CliConfigCmd(configSource: ConfigSource) : CliktCommand("config") { init { subcommands(CliConfigGet(configSource), CliConfigDump(configSource), CliConfigPathsub(configSource)) } + override fun help(context: Context) = "Inspect or change the configuration" + override fun run() = Unit } -private class CliConfigGet(private val configSource: ConfigSource) : CliktCommand("Lookup config value", name = "get") { +private class CliConfigGet(private val configSource: ConfigSource) : CliktCommand("get") { + override fun help(context: Context) = "Lookup config value" + private val common by CommonOption() private val isPath by option( "--filename", "-f", @@ -105,7 +110,9 @@ private class CliConfigGet(private val configSource: ConfigSource) : CliktComman -private class CliConfigPathsub(private val configSource: ConfigSource) : CliktCommand("Substitute variables in a path", name = "pathsub") { +private class CliConfigPathsub(private val configSource: ConfigSource) : CliktCommand("pathsub") { + override fun help(context: Context) = "Substitute variables in a path" + private val common by CommonOption() private val pathExpr by argument() @@ -115,7 +122,9 @@ private class CliConfigPathsub(private val configSource: ConfigSource) : CliktCo } } -private class CliConfigDump(private val configSource: ConfigSource) : CliktCommand("Dump the configuration", name = "dump") { +private class CliConfigDump(private val configSource: ConfigSource) : CliktCommand("dump") { + override fun help(context: Context) = "Dump the configuration" + private val common by CommonOption() override fun run() = cliCmd(logger, common.log) { diff --git a/common/src/main/kotlin/Table.kt b/common/src/main/kotlin/Table.kt @@ -69,7 +69,7 @@ fun printTable( } else { first = false } - val (name, len) = met + val (_, len) = met val pad = len - str.displayLength() if (style.alignLeft) { append(str) diff --git a/common/src/main/kotlin/TalerCommon.kt b/common/src/main/kotlin/TalerCommon.kt @@ -332,6 +332,12 @@ sealed class Payto { } } + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Payto) return false + return this.parsed == other.parsed + } + internal object Serializer : KSerializer<Payto> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Payto", PrimitiveKind.STRING) diff --git a/common/src/main/kotlin/TalerConfig.kt b/common/src/main/kotlin/TalerConfig.kt @@ -109,7 +109,7 @@ data class ConfigSource( for (entry in pathEnv.splitToSequence(':')) { val path = Path(entry) if (path.resolve(execName).exists()) { - val parent = path.getParent() + val parent = path.parent if (parent != null) { return parent.toRealPath() } @@ -127,7 +127,7 @@ data class ConfigSource( * * @param source information about where to load configuration defaults from **/ -private class ConfigLoader internal constructor( +private class ConfigLoader( private val source: ConfigSource ) { private val sections: MutableMap<String, MutableMap<String, String>> = mutableMapOf() @@ -136,7 +136,7 @@ private class ConfigLoader internal constructor( * Load configuration defaults from the file system * and populate the PATHS section based on the installation path. */ - internal fun loadDefaults() { + fun loadDefaults() { val installDir = source.installPath() val section = sections.getOrPut("PATHS") { mutableMapOf() } @@ -187,7 +187,7 @@ private class ConfigLoader internal constructor( return TalerConfigError.generic(message) } - internal fun loadFromFile(file: Path, recursionDepth: Int, lineNum: Int) { + fun loadFromFile(file: Path, recursionDepth: Int, lineNum: Int) { if (recursionDepth > 128) { throw genericError(file, lineNum, "Recursion limit in config inlining") } @@ -205,7 +205,7 @@ private class ConfigLoader internal constructor( } } - internal fun loadFromMem(lines: Sequence<String>, source: Path?, recursionDepth: Int) { + fun loadFromMem(lines: Sequence<String>, source: Path?, recursionDepth: Int) { var currentSection: MutableMap<String, String>? = null for ((lineNum, line) in lines.withIndex()) { if (RE_LINE_OR_COMMENT.matches(line)) { @@ -274,7 +274,7 @@ private class ConfigLoader internal constructor( } } - internal fun finalize(): TalerConfig { + fun finalize(): TalerConfig { return TalerConfig(sections) } @@ -338,7 +338,7 @@ class TalerConfig internal constructor( if (dollarIndex == -1) { // Reached end of string result.append(str, cursor, str.length) - break; + break } // Append normal characters diff --git a/common/src/main/kotlin/TalerMessage.kt b/common/src/main/kotlin/TalerMessage.kt @@ -124,7 +124,8 @@ sealed interface IncomingBankTransaction { val date: TalerProtocolTimestamp val amount: TalerAmount val debit_account: String -}; +} + @Serializable @SerialName("KYCAUTH") data class IncomingKycAuthTransaction( diff --git a/common/src/main/kotlin/crypto/CryptoUtil.kt b/common/src/main/kotlin/crypto/CryptoUtil.kt @@ -280,7 +280,7 @@ object CryptoUtil { gen.init(builder.build()) val result = ByteArray(32) - gen.generateBytes(password.toCharArray(), result, 0, result.size); + gen.generateBytes(password.toCharArray(), result, 0, result.size) return result } } \ No newline at end of file diff --git a/common/src/main/kotlin/db/config.kt b/common/src/main/kotlin/db/config.kt @@ -44,7 +44,6 @@ fun jdbcFromPg(pgConn: String): String { require(pgConn.startsWith("postgresql://") || pgConn.startsWith("postgres://")) { "Not a Postgres connection string: $pgConn" } - var maybeUnixSocket = false val uri = URI(pgConn) val params = parseQueryString(uri.query ?: "", decode = false) diff --git a/common/src/main/kotlin/db/transaction.kt b/common/src/main/kotlin/db/transaction.kt @@ -45,7 +45,18 @@ suspend fun <R> retrySerializationError(lambda: suspend () -> R): R { /** Run a postgres query using a prepared statement */ inline fun <R> PgConnection.withStatement(query: String, lambda: PreparedStatement.() -> R): R { - return prepareStatement(query).use(lambda) + val stmt = prepareStatement(query) + return stmt.use { + val res = stmt.lambda() + // Log warnings + var warning = stmt.getWarnings() + while (warning != null) { + logger.warning(warning.message) + warning = warning.getNextWarning() + } + stmt.clearWarnings() + res + } } /** Run a postgres [transaction] */ diff --git a/common/src/main/kotlin/db/types.kt b/common/src/main/kotlin/db/types.kt @@ -22,12 +22,12 @@ package tech.libeufin.common.db import tech.libeufin.common.* import java.sql.ResultSet -inline fun <reified T : kotlin.Enum<T>> ResultSet.getEnum(name: String): T +inline fun <reified T : Enum<T>> ResultSet.getEnum(name: String): T = java.lang.Enum.valueOf(T::class.java, getString(name)) -inline fun <reified T : kotlin.Enum<T>> ResultSet.getEnum(idx: Int): T +inline fun <reified T : Enum<T>> ResultSet.getEnum(idx: Int): T = java.lang.Enum.valueOf(T::class.java, getString(idx)) -inline fun <reified T : kotlin.Enum<T>> ResultSet.getOptEnum(name: String): T? +inline fun <reified T : Enum<T>> ResultSet.getOptEnum(name: String): T? = getString(name)?.run { java.lang.Enum.valueOf(T::class.java, this) } fun ResultSet.getAmount(name: String, currency: String): TalerAmount { @@ -57,4 +57,8 @@ fun ResultSet.getTalerTimestamp(name: String): TalerProtocolTimestamp{ fun ResultSet.getBankPayto(payto: String, name: String, ctx: BankPaytoCtx): String { return Payto.parse(getString(payto)).bank(getString(name), ctx) +} + +fun ResultSet.getIbanPayto(payto: String): IbanPayto { + return Payto.parse(getString(payto)).expectIban() } \ No newline at end of file diff --git a/common/src/main/kotlin/helpers.kt b/common/src/main/kotlin/helpers.kt @@ -20,6 +20,7 @@ package tech.libeufin.common import io.ktor.server.application.* +import org.slf4j.Logger import java.io.ByteArrayOutputStream import java.io.FilterInputStream import java.io.InputStream @@ -27,6 +28,7 @@ import java.math.BigInteger import java.security.SecureRandom import java.time.Instant import java.time.LocalDate +import java.time.LocalDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.util.* @@ -34,7 +36,6 @@ import java.util.zip.DeflaterInputStream import java.util.zip.InflaterInputStream import java.util.zip.ZipInputStream import kotlin.random.Random -import org.slf4j.Logger /* ----- String ----- */ @@ -60,12 +61,16 @@ fun String.fmtChunkByTwo() = buildString { } } -/* ----- Date ----- */ +/* ----- Date & Time ----- */ /** Converting YYYY-MM-DD to Instant */ fun dateToInstant(date: String): Instant = LocalDate.parse(date, DateTimeFormatter.ISO_DATE).atStartOfDay().toInstant(ZoneOffset.UTC) +/** Converting YYYY-MM-DDTHH:MM:SS to Instant */ +fun dateTimeToInstant(date: String): Instant = + LocalDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME).toInstant(ZoneOffset.UTC) + /* ----- BigInteger -----*/ fun BigInteger.encodeHex(): String = this.toByteArray().encodeHex() @@ -143,7 +148,7 @@ fun Throwable.fmtLog(logger: Logger) { /* ----- Logger ----- */ inline fun Logger.debug(lambda: () -> String) { - if (isDebugEnabled()) debug(lambda()) + if (isDebugEnabled) debug(lambda()) } /* ----- KTOR ----- */ @@ -164,4 +169,10 @@ fun ApplicationCall.longPath(name: String): Long { } catch (e: Exception) { throw badRequest("Long uri component malformed: ${e.message}", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // TODO better error ? } +} + +/* ----- Payto ----- */ + +fun ibanPayto(iban: String, name: String? = null): IbanPayto { + return Payto.parse(IbanPayto.build(iban, null, name)).expectIban() } \ No newline at end of file diff --git a/common/src/main/kotlin/test/bench.kt b/common/src/main/kotlin/test/bench.kt @@ -19,14 +19,9 @@ package tech.libeufin.common.test -import tech.libeufin.common.* -import org.postgresql.jdbc.* import org.postgresql.copy.* -import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneId -import java.util.* -import kotlin.math.max +import org.postgresql.jdbc.* +import tech.libeufin.common.* import kotlin.math.pow import kotlin.math.sqrt import kotlin.time.DurationUnit @@ -46,7 +41,7 @@ fun PgConnection.genData(amount: Int, generators: Sequence<Pair<String, (Int) -> } // Update database statistics for better perf - this.execSQLUpdate("VACUUM ANALYZE"); + this.execSQLUpdate("VACUUM ANALYZE") } class Benchmark(private val iter: Int) { @@ -90,7 +85,6 @@ class Benchmark(private val iter: Int) { fun bench(iter: Int, lambda: Benchmark.() -> Unit) { val bench = Benchmark(iter) lambda(bench) - val cols = IntArray(5) { 0 } printTable( listOf("benchmark", "min", "mean", "max", "std").map { ANSI.bold(it) }, bench.measures, diff --git a/common/src/test/kotlin/ParamsTest.kt b/common/src/test/kotlin/ParamsTest.kt @@ -17,10 +17,10 @@ * <http://www.gnu.org/licenses/> */ +import io.ktor.http.* import org.junit.Test import tech.libeufin.common.* import kotlin.test.* -import io.ktor.http.* class ParamsTest { @Test diff --git a/common/src/test/kotlin/TxMedataTest.kt b/common/src/test/kotlin/TxMedataTest.kt @@ -36,8 +36,6 @@ class TxMetadataTest { val mixed = "4mzt6RS3rvb3b0e2rdmyw0yra3y0vphyv0cyde6xbb0ympfxceg0" val mixedL = "4mzt6rs3rvb3b0e2rdmyw0yra3" val mixedR = "y0vphyv0cyde6xbb0ympfxceg0" - val otherUpper = "TEST6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0" - val otherMixed = "test6rRSrvb3b0e2rdmyw0yra3y0vphyv0cyde6xbb0ympfxceg0" val key = TalerIncomingMetadata(TalerIncomingType.reserve, EddsaPublicKey(upper)) // Check succeed if upper or mixed diff --git a/contrib/ci/jobs/0-codespell/dictionary.txt b/contrib/ci/jobs/0-codespell/dictionary.txt @@ -15,4 +15,5 @@ UE Te optin claus -pres -\ No newline at end of file +pres +haa +\ No newline at end of file diff --git a/contrib/ci/jobs/0-codespell/job.sh b/contrib/ci/jobs/0-codespell/job.sh @@ -19,8 +19,8 @@ configure~ */build/* */*.xsd */*.xml -*/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022ExternalCodeSets.kt -*/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022BankTransactionCode.kt +*/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt +*/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt EOF ); diff --git a/database-versioning/libeufin-bank-0008.sql b/database-versioning/libeufin-bank-0008.sql @@ -0,0 +1,29 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +BEGIN; + +SELECT _v.register_patch('libeufin-bank-0008', NULL, NULL); +SET search_path TO libeufin_bank; + +ALTER TABLE customers RENAME COLUMN login TO username; +ALTER TABLE bank_accounts RENAME internal_payto_uri TO internal_payto; +ALTER TABLE bank_account_transactions RENAME debtor_payto_uri TO debtor_payto; +ALTER TABLE bank_account_transactions RENAME creditor_payto_uri TO creditor_payto; +ALTER TABLE bank_account_transactions + DROP COLUMN account_servicer_reference, + DROP COLUMN payment_information_id, + DROP COLUMN end_to_end_id; +COMMIT; diff --git a/database-versioning/libeufin-bank-procedures.sql b/database-versioning/libeufin-bank-procedures.sql @@ -236,7 +236,7 @@ SELECT has_debt, (balance).val, (balance).frac, (max_debt).val, (max_debt).frac, - internal_payto_uri, customers.name + internal_payto, customers.name INTO debtor_has_debt, debtor_balance.val, debtor_balance.frac, @@ -252,7 +252,7 @@ END IF; SELECT has_debt, (balance).val, (balance).frac, - internal_payto_uri, customers.name + internal_payto, customers.name INTO creditor_has_debt, creditor_balance.val, creditor_balance.frac, @@ -267,14 +267,14 @@ END IF; SELECT bank_account_id, has_debt, (balance).val, (balance).frac, - internal_payto_uri, customers.name + internal_payto, customers.name INTO admin_account_id, admin_has_debt, admin_balance.val, admin_balance.frac, admin_payto, admin_name FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = 'admin'; + WHERE username = 'admin'; IF NOT FOUND THEN RAISE EXCEPTION 'No admin'; END IF; @@ -392,9 +392,9 @@ END IF; -- now actually create the bank transaction. -- debtor side: INSERT INTO bank_account_transactions ( - creditor_payto_uri + creditor_payto ,creditor_name - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,subject ,amount @@ -416,9 +416,9 @@ VALUES ( -- debtor side: INSERT INTO bank_account_transactions ( - creditor_payto_uri + creditor_payto ,creditor_name - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,subject ,amount @@ -454,9 +454,9 @@ WHERE bank_account_id=in_creditor_account_id; -- Fee part IF amount_with_fee != in_amount THEN INSERT INTO bank_account_transactions ( - creditor_payto_uri + creditor_payto ,creditor_name - ,debtor_payto_uri + ,debtor_payto ,debtor_name ,subject ,amount @@ -498,7 +498,7 @@ PERFORM pg_notify('bank_tx', in_debtor_account_id || ' ' || in_creditor_account_ END $$; CREATE FUNCTION account_delete( - IN in_login TEXT, + IN in_username TEXT, IN in_timestamp INT8, IN in_is_tan BOOLEAN, OUT out_not_found BOOLEAN, @@ -520,7 +520,7 @@ SELECT ,out_balance_not_zero FROM customers JOIN bank_accounts ON owning_customer_id = customer_id - WHERE login = in_login AND deleted_at IS NULL; + WHERE username = in_username AND deleted_at IS NULL; IF NOT FOUND OR out_balance_not_zero OR out_tan_required THEN out_not_found=NOT FOUND; RETURN; @@ -639,7 +639,7 @@ credit_row_id INT8; BEGIN -- Check for idempotence and conflict SELECT (amount != in_amount - OR creditor_payto_uri != in_credit_account_payto + OR creditor_payto != in_credit_account_payto OR exchange_base_url != in_exchange_base_url OR wtid != in_wtid) ,bank_transaction_id, transaction_date @@ -658,7 +658,7 @@ SELECT FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = in_username AND deleted_at IS NULL; + WHERE username = in_username AND deleted_at IS NULL; IF NOT FOUND OR out_debtor_not_exchange THEN out_debtor_not_found=NOT FOUND; RETURN; @@ -668,7 +668,7 @@ SELECT bank_account_id, is_taler_exchange INTO receiver_bank_account_id, out_both_exchanges FROM bank_accounts - WHERE internal_payto_uri = in_credit_account_payto; + WHERE internal_payto = in_credit_account_payto; IF NOT FOUND OR out_both_exchanges THEN out_creditor_not_found=NOT FOUND; RETURN; @@ -738,7 +738,7 @@ SELECT FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = in_username AND deleted_at IS NULL; + WHERE username = in_username AND deleted_at IS NULL; IF NOT FOUND OR out_creditor_not_exchange THEN out_creditor_not_found=NOT FOUND; RETURN; @@ -748,7 +748,7 @@ SELECT bank_account_id, is_taler_exchange INTO sender_bank_account_id, out_both_exchanges FROM bank_accounts - WHERE internal_payto_uri = in_debit_account_payto; + WHERE internal_payto = in_debit_account_payto; IF NOT FOUND OR out_both_exchanges THEN out_debtor_not_found=NOT FOUND; RETURN; @@ -814,11 +814,11 @@ CREATE FUNCTION bank_transaction( LANGUAGE plpgsql AS $$ BEGIN -- Find credit bank account id and check it's not admin -SELECT bank_account_id, is_taler_exchange, login='admin' +SELECT bank_account_id, is_taler_exchange, username='admin' INTO out_credit_bank_account_id, out_creditor_is_exchange, out_creditor_admin FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE internal_payto_uri = in_credit_account_payto AND deleted_at IS NULL; + WHERE internal_payto = in_credit_account_payto AND deleted_at IS NULL; IF NOT FOUND OR out_creditor_admin THEN out_creditor_not_found=NOT FOUND; RETURN; @@ -828,7 +828,7 @@ SELECT bank_account_id, is_taler_exchange, out_credit_bank_account_id=bank_accou INTO out_debit_bank_account_id, out_debtor_is_exchange, out_same_account, out_tan_required FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = in_debit_account_username AND deleted_at IS NULL; + WHERE username = in_debit_account_username AND deleted_at IS NULL; IF NOT FOUND OR out_same_account THEN out_debtor_not_found=NOT FOUND; RETURN; @@ -908,7 +908,7 @@ SELECT bank_account_id, is_taler_exchange INTO account_id, out_account_is_exchange FROM bank_accounts JOIN customers ON bank_accounts.owning_customer_id = customers.customer_id - WHERE login=in_account_username AND deleted_at IS NULL; + WHERE username=in_account_username AND deleted_at IS NULL; IF NOT FOUND OR out_account_is_exchange THEN out_account_not_found=NOT FOUND; RETURN; @@ -997,7 +997,7 @@ IF not_selected THEN SELECT NOT is_taler_exchange INTO out_account_is_not_exchange FROM bank_accounts - WHERE internal_payto_uri=in_selected_exchange_payto; + WHERE internal_payto=in_selected_exchange_payto; IF NOT FOUND OR out_account_is_not_exchange THEN out_account_not_found=NOT FOUND; RETURN; @@ -1054,7 +1054,7 @@ END $$; COMMENT ON FUNCTION abort_taler_withdrawal IS 'Abort a withdrawal operation.'; CREATE FUNCTION confirm_taler_withdrawal( - IN in_login TEXT, + IN in_username TEXT, IN in_withdrawal_uuid uuid, IN in_timestamp INT8, IN in_is_tan BOOLEAN, @@ -1101,7 +1101,7 @@ SELECT FROM taler_withdrawal_operations JOIN bank_accounts ON wallet_bank_account=bank_account_id JOIN customers ON owning_customer_id=customer_id - WHERE withdrawal_uuid=in_withdrawal_uuid AND login=in_login AND deleted_at IS NULL; + WHERE withdrawal_uuid=in_withdrawal_uuid AND username=in_username AND deleted_at IS NULL; IF NOT FOUND OR already_confirmed OR out_aborted OR out_not_selected THEN out_no_op=NOT FOUND; RETURN; @@ -1112,7 +1112,7 @@ SELECT bank_account_id INTO exchange_bank_account_id FROM bank_accounts - WHERE internal_payto_uri = selected_exchange_payto_local; + WHERE internal_payto = selected_exchange_payto_local; IF NOT FOUND OR out_tan_required THEN out_exchange_not_found=NOT FOUND; RETURN; @@ -1177,7 +1177,7 @@ SELECT bank_account_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = 'exchange'; + WHERE username = 'exchange'; IF NOT FOUND THEN out_no_account = true; RETURN; @@ -1189,7 +1189,7 @@ SELECT bank_account_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = 'admin'; + WHERE username = 'admin'; -- Perform conversion SELECT (converted).val, (converted).frac, too_small, no_config @@ -1231,7 +1231,7 @@ COMMENT ON FUNCTION cashin IS 'Perform a cashin operation'; CREATE FUNCTION cashout_create( - IN in_login TEXT, + IN in_username TEXT, IN in_request_uid BYTEA, IN in_amount_debit taler_amount, IN in_amount_credit taler_amount, @@ -1269,7 +1269,7 @@ SELECT out_no_cashout_payto, out_tan_required FROM bank_accounts JOIN customers ON owning_customer_id=customer_id - WHERE login=in_login; + WHERE username=in_username; IF NOT FOUND THEN out_account_not_found=TRUE; RETURN; @@ -1294,7 +1294,7 @@ SELECT bank_account_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id - WHERE login = 'admin'; + WHERE username = 'admin'; -- Check for idempotence and conflict SELECT (amount_debit != in_amount_debit @@ -1355,7 +1355,7 @@ CREATE FUNCTION tan_challenge_create ( IN in_timestamp INT8, IN in_validity_period INT8, IN in_retry_counter INT4, - IN in_login TEXT, + IN in_username TEXT, IN in_tan_channel tan_enum, IN in_tan_info TEXT, OUT out_challenge_id INT8 @@ -1365,7 +1365,7 @@ DECLARE account_id INT8; BEGIN -- Retrieve account id -SELECT customer_id INTO account_id FROM customers WHERE login = in_login AND deleted_at IS NULL; +SELECT customer_id INTO account_id FROM customers WHERE username = in_username AND deleted_at IS NULL; -- Create challenge INSERT INTO tan_challenges ( body, @@ -1393,7 +1393,7 @@ COMMENT ON FUNCTION tan_challenge_create IS 'Create a new challenge, return the CREATE FUNCTION tan_challenge_send ( IN in_challenge_id INT8, - IN in_login TEXT, + IN in_username TEXT, IN in_code TEXT, -- New code to use if the old code expired IN in_timestamp INT8, IN in_validity_period INT8, @@ -1417,7 +1417,7 @@ SELECT customer_id, tan_channel, CASE tan_channel WHEN 'email' THEN email END INTO account_id, out_tan_channel, out_tan_info -FROM customers WHERE login = in_login AND deleted_at IS NULL; +FROM customers WHERE username = in_username AND deleted_at IS NULL; -- Recover expiration date SELECT @@ -1458,7 +1458,7 @@ COMMENT ON FUNCTION tan_challenge_mark_sent IS 'Register a challenge as successf CREATE FUNCTION tan_challenge_try ( IN in_challenge_id INT8, - IN in_login TEXT, + IN in_username TEXT, IN in_code TEXT, IN in_timestamp INT8, -- Error status @@ -1477,7 +1477,7 @@ DECLARE account_id INT8; BEGIN -- Retrieve account id -SELECT customer_id INTO account_id FROM customers WHERE login = in_login AND deleted_at IS NULL; +SELECT customer_id INTO account_id FROM customers WHERE username = in_username AND deleted_at IS NULL; -- Check challenge UPDATE tan_challenges SET confirmation_date = CASE diff --git a/database-versioning/libeufin-conversion-setup.sql b/database-versioning/libeufin-conversion-setup.sql @@ -18,16 +18,20 @@ LANGUAGE plpgsql AS $$ WHERE bank_account_id=NEW.bank_account; INSERT INTO libeufin_nexus.initiated_outgoing_transactions ( amount - ,wire_transfer_subject - ,credit_payto_uri + ,subject + ,credit_payto ,initiation_time - ,request_uid + ,end_to_end_id ) VALUES ( ((NEW.amount_credit).val, (NEW.amount_credit).frac)::libeufin_nexus.taler_amount ,NEW.subject ,payto_uri ,now_date - ,LEFT(gen_random_uuid()::text, 35) + -- use gen_random_uuid to get some randomness + -- remove all - characters as they are not random + -- capitalise the UUID as some bank may still be case sensitive + -- end with 34 random chars which is valid for EBICS (max 35 chars) + ,upper(replace(gen_random_uuid()::text, '-', '')) ); END IF; RETURN NEW; @@ -43,7 +47,7 @@ LANGUAGE plpgsql AS $$ DECLARE now_date INT8; local_amount libeufin_bank.taler_amount; - subject TEXT; + local_subject TEXT; too_small BOOLEAN; balance_insufficient BOOLEAN; no_account BOOLEAN; @@ -54,20 +58,29 @@ LANGUAGE plpgsql AS $$ RETURN NEW; END IF; - SELECT (amount).val, (amount).frac, wire_transfer_subject, execution_time - INTO local_amount.val, local_amount.frac, subject, now_date + SELECT (amount).val, (amount).frac, subject, execution_time + INTO local_amount.val, local_amount.frac, local_subject, now_date FROM libeufin_nexus.incoming_transactions WHERE incoming_transaction_id = NEW.incoming_transaction_id; SET search_path TO libeufin_bank; SELECT out_too_small, out_balance_insufficient, out_no_account, out_no_config INTO too_small, balance_insufficient, no_account, no_config - FROM libeufin_bank.cashin(now_date, NEW.reserve_public_key, local_amount, subject); + FROM libeufin_bank.cashin(now_date, NEW.reserve_public_key, local_amount, local_subject); SET search_path TO libeufin_nexus; -- Bounce on soft failures IF too_small THEN -- TODO bounce fees ? - PERFORM bounce_incoming(NEW.incoming_transaction_id, ((local_amount).val, (local_amount).frac)::taler_amount, now_date); + PERFORM bounce_incoming( + NEW.incoming_transaction_id + ,((local_amount).val, (local_amount).frac)::taler_amount + -- use gen_random_uuid to get some randomness + -- remove all - characters as they are not random + -- capitalise the UUID as some bank may still be case sensitive + -- end with 34 random chars which is valid for EBICS (max 35 chars) + ,upper(replace(gen_random_uuid()::text, '-', '')) + ,now_date + ); RETURN NULL; END IF; diff --git a/database-versioning/libeufin-nexus-0007.sql b/database-versioning/libeufin-nexus-0007.sql @@ -0,0 +1,77 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +BEGIN; + +SELECT _v.register_patch('libeufin-nexus-0007', NULL, NULL); + +-- Add a new submission state reusing a currently unused slot +ALTER TYPE submission_state RENAME VALUE 'never_heard_back' TO 'pending'; +ALTER TYPE submission_state ADD VALUE 'late_failure'; + +-- Batch of initiated_outgoing_transactions +CREATE TABLE initiated_outgoing_batches( + initiated_outgoing_batch_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE, + creation_date INT8 NOT NULL, + sum taler_amount NOT NULL DEFAULT (0, 0), + message_id TEXT NOT NULL UNIQUE CHECK (char_length(message_id) <= 35), + order_id TEXT UNIQUE, + submission_date INT8, + submission_counter INT4 NOT NULL DEFAULT 0, + status submission_state NOT NULL DEFAULT 'unsubmitted', + status_msg TEXT +); +COMMENT ON COLUMN initiated_outgoing_transactions.order_id + IS 'Order ID of the EBICS upload transaction, used to track EBICS order status.'; + +-- Add batch column to initiated_outgoing_transactions +ALTER TABLE initiated_outgoing_transactions + ADD COLUMN initiated_outgoing_batch_id INT8 REFERENCES initiated_outgoing_batches (initiated_outgoing_batch_id); + +-- Create a batch for all existing initiated_outgoing_transactions +INSERT INTO initiated_outgoing_batches(creation_date, message_id, order_id, submission_date, submission_counter, status, status_msg) + SELECT initiation_time, request_uid, order_id, last_submission_time, submission_counter, (CASE WHEN submitted = 'success' OR submitted = 'permanent_failure' THEN 'success' ELSE 'pending' END)::submission_state, failure_message + FROM initiated_outgoing_transactions; + +-- Link initiated_outgoing_transactions to their initiated_outgoing_batches +UPDATE initiated_outgoing_transactions SET initiated_outgoing_batch_id = ( + SELECT initiated_outgoing_batch_id FROM initiated_outgoing_batches WHERE request_uid=message_id +); + +-- Drop now unused columns from initiated_outgoing_transactions and rename some +ALTER TABLE initiated_outgoing_transactions + DROP COLUMN order_id, + DROP COLUMN last_submission_time, + DROP COLUMN submission_counter, + DROP COLUMN hidden; + +-- Add necessary indexes +CREATE INDEX initiated_outgoing_batches_status_index ON initiated_outgoing_batches (status); +COMMENT ON INDEX initiated_outgoing_batches_status_index IS 'for listing taler batch by status for a future admin UI'; +CREATE INDEX initiated_outgoing_transactions_batch_index ON initiated_outgoing_transactions (initiated_outgoing_batch_id); +COMMENT ON INDEX initiated_outgoing_transactions_batch_index IS 'for listing transactions in batches'; + +-- Renaming +ALTER TABLE incoming_transactions RENAME COLUMN wire_transfer_subject TO subject; +ALTER TABLE incoming_transactions RENAME COLUMN debit_payto_uri TO debit_payto; +ALTER TABLE outgoing_transactions RENAME COLUMN wire_transfer_subject TO subject; +ALTER TABLE outgoing_transactions RENAME COLUMN credit_payto_uri TO credit_payto; +ALTER TABLE outgoing_transactions RENAME COLUMN message_id TO end_to_end_id; +ALTER TABLE initiated_outgoing_transactions RENAME COLUMN wire_transfer_subject TO subject; +ALTER TABLE initiated_outgoing_transactions RENAME COLUMN credit_payto_uri TO credit_payto; +ALTER TABLE initiated_outgoing_transactions RENAME COLUMN submitted TO status; +ALTER TABLE initiated_outgoing_transactions RENAME COLUMN failure_message TO status_msg; +ALTER TABLE initiated_outgoing_transactions RENAME COLUMN request_uid TO end_to_end_id; +COMMIT; diff --git a/database-versioning/libeufin-nexus-procedures.sql b/database-versioning/libeufin-nexus-procedures.sql @@ -27,14 +27,45 @@ BEGIN END $do$; +CREATE FUNCTION amount_normalize( + IN amount taler_amount + ,OUT normalized taler_amount +) +LANGUAGE plpgsql IMMUTABLE AS $$ +BEGIN + normalized.val = amount.val + amount.frac / 100000000; + IF (normalized.val > 1::INT8<<52) THEN + RAISE EXCEPTION 'amount value overflowed'; + END IF; + normalized.frac = amount.frac % 100000000; + +END $$; +COMMENT ON FUNCTION amount_normalize + IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.' + 'It raises an exception when the resulting .val is larger than 2^52'; + +CREATE FUNCTION amount_add( + IN l taler_amount + ,IN r taler_amount + ,OUT sum taler_amount +) +LANGUAGE plpgsql IMMUTABLE AS $$ +BEGIN + sum = (l.val + r.val, l.frac + r.frac); + SELECT normalized.val, normalized.frac INTO sum.val, sum.frac FROM amount_normalize(sum) as normalized; +END $$; +COMMENT ON FUNCTION amount_add + IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52'; + CREATE FUNCTION register_outgoing( IN in_amount taler_amount - ,IN in_wire_transfer_subject TEXT + ,IN in_subject TEXT ,IN in_execution_time INT8 - ,IN in_credit_payto_uri TEXT - ,IN in_message_id TEXT + ,IN in_credit_payto TEXT + ,IN in_end_to_end_id TEXT ,IN in_wtid BYTEA ,IN in_exchange_url TEXT + ,IN in_msg_id TEXT ,OUT out_tx_id INT8 ,OUT out_found BOOLEAN ,OUT out_initiated BOOLEAN @@ -42,56 +73,118 @@ CREATE FUNCTION register_outgoing( LANGUAGE plpgsql AS $$ DECLARE init_id INT8; +local_amount taler_amount; +local_subject TEXT; +local_credit_payto TEXT; +local_wtid BYTEA; +local_exchange_base_url TEXT; +local_end_to_end_id TEXT; BEGIN -- Check if already registered -SELECT outgoing_transaction_id INTO out_tx_id - FROM outgoing_transactions - WHERE message_id = in_message_id; -IF FOUND THEN - out_found = true; - -- TODO Should we update the subject and credit payto if it's finally found - -- TODO Should we check that amount and other info match ? - SELECT true INTO out_initiated - FROM initiated_outgoing_transactions - WHERE outgoing_transaction_id = out_tx_id; -ELSE +SELECT outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, + wtid, exchange_base_url + INTO out_tx_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, + local_wtid, local_exchange_base_url + FROM outgoing_transactions LEFT JOIN talerable_outgoing_transactions USING (outgoing_transaction_id) + WHERE end_to_end_id = in_end_to_end_id; +out_found=FOUND; +IF out_found THEN + -- Check metadata + -- TODO take subject if missing and more detailed credit payto + IF local_subject IS DISTINCT FROM in_subject THEN + RAISE NOTICE 'outgoing tx %: stored subject is ''%'' got ''%''', in_end_to_end_id, local_subject, in_subject; + END IF; + IF local_credit_payto IS DISTINCT FROM in_credit_payto THEN + RAISE NOTICE 'outgoing tx %: stored subject credit payto is % got %', in_end_to_end_id, local_credit_payto, in_credit_payto; + END IF; + IF local_amount IS DISTINCT FROM in_amount THEN + RAISE NOTICE 'outgoing tx %: stored amount is % got %', in_end_to_end_id, local_amount, in_amount; + END IF; + IF local_wtid IS DISTINCT FROM in_wtid THEN + RAISE NOTICE 'outgoing tx %: stored wtid is % got %', in_end_to_end_id, local_wtid, in_wtid; + END IF; + IF local_exchange_base_url IS DISTINCT FROM in_exchange_url THEN + RAISE NOTICE 'outgoing tx %: stored exchange base url is % got %', in_end_to_end_id, local_exchange_base_url, in_exchange_url; + END IF; +END IF; + +-- Check if initiated +SELECT initiated_outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, + wtid, exchange_base_url + INTO init_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, + local_wtid, local_exchange_base_url + FROM initiated_outgoing_transactions LEFT JOIN transfer_operations USING (initiated_outgoing_transaction_id) + WHERE end_to_end_id = in_end_to_end_id; +out_initiated=FOUND; +IF out_initiated AND NOT out_found THEN + -- Check metadata + -- TODO take subject if missing and more detailed credit payto + IF local_subject IS DISTINCT FROM in_subject THEN + RAISE NOTICE 'outgoing tx %: initiated subject is ''%'' got ''%''', in_end_to_end_id, local_subject, in_subject; + END IF; + IF local_credit_payto IS DISTINCT FROM in_credit_payto THEN + RAISE NOTICE 'outgoing tx %: initiated subject credit payto is % got %', in_end_to_end_id, local_credit_payto, in_credit_payto; + END IF; + IF local_amount IS DISTINCT FROM in_amount THEN + RAISE NOTICE 'outgoing tx %: initiated amount is % got %', in_end_to_end_id, local_amount, in_amount; + END IF; + IF local_wtid IS DISTINCT FROM in_wtid THEN + RAISE NOTICE 'outgoing tx %: initiated wtid is % got %', in_end_to_end_id, local_wtid, in_wtid; + END IF; + IF local_exchange_base_url IS DISTINCT FROM in_exchange_url THEN + RAISE NOTICE 'outgoing tx %: initiated exchange base url is % got %', in_end_to_end_id, local_exchange_base_url, in_exchange_url; + END IF; +END IF; + +IF NOT out_found THEN -- Store the transaction in the database INSERT INTO outgoing_transactions ( - amount - ,wire_transfer_subject + amount + ,subject ,execution_time - ,credit_payto_uri - ,message_id + ,credit_payto + ,end_to_end_id ) VALUES ( - in_amount - ,in_wire_transfer_subject + in_amount + ,in_subject ,in_execution_time - ,in_credit_payto_uri - ,in_message_id + ,in_credit_payto + ,in_end_to_end_id ) RETURNING outgoing_transaction_id INTO out_tx_id; - -- Reconciles the related initiated transaction - UPDATE initiated_outgoing_transactions - SET - outgoing_transaction_id = out_tx_id - ,submitted = 'success' - ,failure_message = null - WHERE request_uid = in_message_id - RETURNING true INTO out_initiated; -END IF; + -- Register as talerable if contains wtid and exchange URL + IF in_wtid IS NOT NULL OR in_exchange_url IS NOT NULL THEN + SELECT end_to_end_id INTO local_end_to_end_id + FROM talerable_outgoing_transactions + JOIN outgoing_transactions USING (outgoing_transaction_id) + WHERE wtid=in_wtid; + IF FOUND THEN + IF local_end_to_end_id != in_end_to_end_id THEN + RAISE NOTICE 'wtid reuse: tx % and tx % have the same wtid %', in_end_to_end_id, local_end_to_end_id, in_wtid; + END IF; + ELSE + INSERT INTO talerable_outgoing_transactions(outgoing_transaction_id, wtid, exchange_base_url) + VALUES (out_tx_id, in_wtid, in_exchange_url); + PERFORM pg_notify('nexus_outgoing_tx', out_tx_id::text); + END IF; + END IF; --- Register as talerable if contains wtid and exchange URL -IF in_wtid IS NOT NULL OR in_exchange_url IS NOT NULL THEN - INSERT INTO talerable_outgoing_transactions ( - outgoing_transaction_id, - wtid, - exchange_base_url - ) VALUES (out_tx_id, in_wtid, in_exchange_url) - ON CONFLICT (wtid) DO NOTHING; - IF FOUND THEN - PERFORM pg_notify('nexus_outgoing_tx', out_tx_id::text); + IF out_initiated THEN + -- Reconciles the related initiated transaction + UPDATE initiated_outgoing_transactions + SET + outgoing_transaction_id = out_tx_id + ,status = 'success' + ,status_msg = null + WHERE initiated_outgoing_transaction_id = init_id + AND status != 'late_failure'; + + -- Reconciles the related initiated batch + UPDATE initiated_outgoing_batches + SET status = 'success', status_msg = null + WHERE message_id = in_msg_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); END IF; END IF; END $$; @@ -100,125 +193,9 @@ COMMENT ON FUNCTION register_outgoing CREATE FUNCTION register_incoming( IN in_amount taler_amount - ,IN in_wire_transfer_subject TEXT + ,IN in_subject TEXT ,IN in_execution_time INT8 - ,IN in_debit_payto_uri TEXT - ,IN in_bank_id TEXT - ,OUT out_found BOOLEAN - ,OUT out_tx_id INT8 -) -LANGUAGE plpgsql AS $$ -BEGIN --- Check if already registered -SELECT incoming_transaction_id INTO out_tx_id - FROM incoming_transactions - WHERE bank_id = in_bank_id; -IF FOUND THEN - out_found = true; - -- TODO Should we check that amount and other info match ? -ELSE - -- Store the transaction in the database - INSERT INTO incoming_transactions ( - amount - ,wire_transfer_subject - ,execution_time - ,debit_payto_uri - ,bank_id - ) VALUES ( - in_amount - ,in_wire_transfer_subject - ,in_execution_time - ,in_debit_payto_uri - ,in_bank_id - ) RETURNING incoming_transaction_id INTO out_tx_id; - PERFORM pg_notify('nexus_revenue_tx', out_tx_id::text); -END IF; -END $$; -COMMENT ON FUNCTION register_incoming - IS 'Register an incoming transaction'; - -CREATE FUNCTION bounce_incoming( - IN tx_id INT8 - ,IN in_bounce_amount taler_amount - ,IN in_now_date INT8 - ,OUT out_bounce_id TEXT -) -LANGUAGE plpgsql AS $$ -DECLARE -local_bank_id TEXT; -payto_uri TEXT; -init_id INT8; -BEGIN --- Get incoming transaction bank ID and creditor -SELECT bank_id, debit_payto_uri - INTO local_bank_id, payto_uri - FROM incoming_transactions - WHERE incoming_transaction_id = tx_id; --- Generate a bounce ID deterministically from the bank ID --- We hash the bank ID with SHA-256 then we encode the hash using base64 --- As bank id can be at most 35 characters long we truncate the encoded hash --- We are not sure whether this field is case-insensitive in all banks as the standard --- does not clearly specify this, so we have chosen to capitalise it -SELECT upper(substr(encode(public.digest(local_bank_id, 'sha256'), 'base64'), 0, 35)) INTO out_bounce_id; - --- Initiate the bounce transaction -INSERT INTO initiated_outgoing_transactions ( - amount - ,wire_transfer_subject - ,credit_payto_uri - ,initiation_time - ,request_uid - ) VALUES ( - in_bounce_amount - ,'bounce: ' || local_bank_id - ,payto_uri - ,in_now_date - ,out_bounce_id - ) - ON CONFLICT (request_uid) DO NOTHING -- idempotent - RETURNING initiated_outgoing_transaction_id INTO init_id; -IF FOUND THEN - -- Register the bounce - INSERT INTO bounced_transactions ( - incoming_transaction_id ,initiated_outgoing_transaction_id - ) VALUES (tx_id, init_id); -END IF; -END$$; -COMMENT ON FUNCTION bounce_incoming - IS 'Bounce an incoming transaction, initiate a bounce outgoing transaction with a deterministic ID'; - -CREATE FUNCTION register_incoming_and_bounce( - IN in_amount taler_amount - ,IN in_wire_transfer_subject TEXT - ,IN in_execution_time INT8 - ,IN in_debit_payto_uri TEXT - ,IN in_bank_id TEXT - ,IN in_bounce_amount taler_amount - ,IN in_now_date INT8 - ,OUT out_found BOOLEAN - ,OUT out_tx_id INT8 - ,OUT out_bounce_id TEXT -) -LANGUAGE plpgsql AS $$ -DECLARE -init_id INT8; -BEGIN --- Register the incoming transaction -SELECT reg.out_found, reg.out_tx_id - FROM register_incoming(in_amount, in_wire_transfer_subject, in_execution_time, in_debit_payto_uri, in_bank_id) as reg - INTO out_found, out_tx_id; - --- Bounce the incoming transaction -SELECT b.out_bounce_id INTO out_bounce_id FROM bounce_incoming(out_tx_id, in_bounce_amount, in_now_date) as b; -END $$; -COMMENT ON FUNCTION register_incoming_and_bounce - IS 'Register an incoming transaction and bounce it'; - -CREATE FUNCTION register_incoming_and_talerable( - IN in_amount taler_amount - ,IN in_wire_transfer_subject TEXT - ,IN in_execution_time INT8 - ,IN in_debit_payto_uri TEXT + ,IN in_debit_payto TEXT ,IN in_bank_id TEXT ,IN in_type taler_incoming_type ,IN in_reserve_pub BYTEA @@ -232,15 +209,20 @@ CREATE FUNCTION register_incoming_and_talerable( LANGUAGE plpgsql AS $$ DECLARE need_reconcile BOOLEAN; +local_amount taler_amount; +local_subject TEXT; +local_debit_payto TEXT; BEGIN -IF in_type = 'reserve' THEN +IF in_type IS NULL THEN + -- No talerable logic +ELSIF in_type = 'reserve' THEN -- Search if already inserted based on unique reserve_pub key -- Reconcile missing bank_id if metadata match -- Check for reserve_pub reuse SELECT incoming_transaction_id, bank_id IS DISTINCT FROM in_bank_id, bank_id IS NULL AND amount = in_amount - AND debit_payto_uri = in_debit_payto_uri - AND wire_transfer_subject = in_wire_transfer_subject + AND debit_payto = in_debit_payto + AND subject = in_subject INTO out_tx_id, out_reserve_pub_reuse, need_reconcile FROM talerable_incoming_transactions JOIN incoming_transactions USING(incoming_transaction_id) @@ -264,8 +246,8 @@ ELSIF in_type = 'kyc' THEN JOIN incoming_transactions USING(incoming_transaction_id) WHERE account_pub = in_account_pub AND amount = in_amount - AND debit_payto_uri = in_debit_payto_uri - AND wire_transfer_subject = in_wire_transfer_subject; + AND debit_payto = in_debit_payto + AND subject = in_subject; IF FOUND THEN -- If bank_id is missing we assume it's the same transaction @@ -282,13 +264,43 @@ ELSE RAISE EXCEPTION 'Unsupported incoming type %', in_type; END IF; --- Register the incoming transaction -SELECT reg.out_found, reg.out_tx_id - FROM register_incoming(in_amount, in_wire_transfer_subject, in_execution_time, in_debit_payto_uri, in_bank_id) as reg - INTO out_found, out_tx_id; +-- Check if already registered +SELECT incoming_transaction_id, subject, debit_payto, (amount).val, (amount).frac + INTO out_tx_id, local_subject, local_debit_payto, local_amount.val, local_amount.frac + FROM incoming_transactions + WHERE bank_id = in_bank_id; +out_found=FOUND; +IF out_found THEN + -- Check metadata + IF local_subject != in_subject THEN + RAISE NOTICE 'incoming tx %: stored subject is ''%'' got ''%''', in_bank_id, local_subject, in_subject; + END IF; + IF local_debit_payto != in_debit_payto THEN + RAISE NOTICE 'incoming tx %: stored subject debit payto is % got %', in_bank_id, local_debit_payto, in_debit_payto; + END IF; + IF local_amount != in_amount THEN + RAISE NOTICE 'incoming tx %: stored amount is % got %', in_bank_id, local_amount, in_amount; + END IF; +ELSE + -- Store the transaction in the database + INSERT INTO incoming_transactions ( + amount + ,subject + ,execution_time + ,debit_payto + ,bank_id + ) VALUES ( + in_amount + ,in_subject + ,in_execution_time + ,in_debit_payto + ,in_bank_id + ) RETURNING incoming_transaction_id INTO out_tx_id; + PERFORM pg_notify('nexus_revenue_tx', out_tx_id::text); +END IF; -- Register as talerable -IF NOT EXISTS(SELECT FROM talerable_incoming_transactions WHERE incoming_transaction_id = out_tx_id) THEN +IF in_type IS NOT NULL AND NOT EXISTS(SELECT FROM talerable_incoming_transactions WHERE incoming_transaction_id = out_tx_id) THEN -- We cannot use ON CONFLICT here because conversion use a trigger before insertion that isn't idempotent INSERT INTO talerable_incoming_transactions ( incoming_transaction_id @@ -304,10 +316,80 @@ IF NOT EXISTS(SELECT FROM talerable_incoming_transactions WHERE incoming_transac PERFORM pg_notify('nexus_incoming_tx', out_tx_id::text); END IF; END $$; -COMMENT ON FUNCTION register_incoming_and_talerable IS ' -Creates one row in the incoming transactions table and one row -in the talerable transactions table. The talerable row links the -incoming one.'; + +CREATE FUNCTION register_and_bounce_incoming( + IN in_amount taler_amount + ,IN in_subject TEXT + ,IN in_execution_time INT8 + ,IN in_debit_payto TEXT + ,IN in_bank_id TEXT + ,IN in_bounce_amount taler_amount + ,IN in_now_date INT8 + ,IN in_bounce_id TEXT + ,OUT out_found BOOLEAN + ,OUT out_tx_id INT8 + ,OUT out_bounce_id TEXT +) +LANGUAGE plpgsql AS $$ +DECLARE +init_id INT8; +BEGIN +-- Register incoming transaction +SELECT reg.out_found, reg.out_tx_id + FROM register_incoming(in_amount, in_subject, in_execution_time, in_debit_payto, in_bank_id, NULL, NULL, NULL) as reg + INTO out_found, out_tx_id; + +-- Bounce incoming transaction +SELECT bounce.out_bounce_id INTO out_bounce_id FROM bounce_incoming(out_tx_id, in_bounce_amount, in_bounce_id, in_now_date) AS bounce; +END $$; + +CREATE FUNCTION bounce_incoming( + IN in_tx_id INT8 + ,IN in_bounce_amount taler_amount + ,IN in_bounce_id TEXT + ,IN in_now_date INT8 + ,OUT out_bounce_id TEXT +) +LANGUAGE plpgsql AS $$ +DECLARE +local_bank_id TEXT; +payto_uri TEXT; +init_id INT8; +BEGIN +-- Check if already bounce +SELECT end_to_end_id INTO out_bounce_id + FROM initiated_outgoing_transactions + JOIN bounced_transactions USING (initiated_outgoing_transaction_id) + WHERE incoming_transaction_id = in_tx_id; + +-- Else initiate the bounce transaction +IF NOT FOUND THEN + out_bounce_id = in_bounce_id; + -- Get incoming transaction bank ID and creditor + SELECT bank_id, debit_payto + INTO local_bank_id, payto_uri + FROM incoming_transactions + WHERE incoming_transaction_id = in_tx_id; + -- Initiate the bounce transaction + INSERT INTO initiated_outgoing_transactions ( + amount + ,subject + ,credit_payto + ,initiation_time + ,end_to_end_id + ) VALUES ( + in_bounce_amount + ,'bounce: ' || local_bank_id + ,payto_uri + ,in_now_date + ,in_bounce_id + ) + RETURNING initiated_outgoing_transaction_id INTO init_id; + -- Register the bounce + INSERT INTO bounced_transactions (incoming_transaction_id, initiated_outgoing_transaction_id) + VALUES (in_tx_id, init_id); +END IF; +END$$; CREATE FUNCTION taler_transfer( IN in_request_uid BYTEA, @@ -316,7 +398,7 @@ CREATE FUNCTION taler_transfer( IN in_amount taler_amount, IN in_exchange_base_url TEXT, IN in_credit_account_payto TEXT, - IN in_bank_id TEXT, + IN in_end_to_end_id TEXT, IN in_timestamp INT8, -- Error status OUT out_request_uid_reuse BOOLEAN, @@ -328,7 +410,7 @@ LANGUAGE plpgsql AS $$ BEGIN -- Check for idempotence and conflict SELECT (amount != in_amount - OR credit_payto_uri != in_credit_account_payto + OR credit_payto != in_credit_account_payto OR exchange_base_url != in_exchange_base_url OR wtid != in_wtid) ,transfer_operations.initiated_outgoing_transaction_id, initiation_time @@ -343,16 +425,16 @@ END IF; -- Initiate bank transfer INSERT INTO initiated_outgoing_transactions ( amount - ,wire_transfer_subject - ,credit_payto_uri + ,subject + ,credit_payto ,initiation_time - ,request_uid + ,end_to_end_id ) VALUES ( in_amount ,in_subject ,in_credit_account_payto ,in_timestamp - ,in_bank_id + ,in_end_to_end_id ) RETURNING initiated_outgoing_transaction_id INTO out_tx_row_id; -- Register outgoing transaction INSERT INTO transfer_operations( @@ -369,3 +451,105 @@ INSERT INTO transfer_operations( out_timestamp = in_timestamp; PERFORM pg_notify('nexus_outgoing_tx', out_tx_row_id::text); END $$; + +CREATE FUNCTION batch_outgoing_transactions( + IN in_timestamp INT8, + IN batch_ebics_id TEXT +) +RETURNS void +LANGUAGE plpgsql AS $$ +DECLARE +batch_id INT8; +local_sum taler_amount DEFAULT (0, 0)::taler_amount; +tx record; +BEGIN +-- Create a new batch only if some transactions are not batched +IF (EXISTS(SELECT FROM initiated_outgoing_transactions WHERE initiated_outgoing_batch_id IS NULL)) THEN + -- Create batch + INSERT INTO initiated_outgoing_batches (creation_date, message_id) + VALUES (in_timestamp, batch_ebics_id) + RETURNING initiated_outgoing_batch_id INTO batch_id; + -- Link batched payment while computing the sum of amounts + FOR tx IN UPDATE initiated_outgoing_transactions + SET initiated_outgoing_batch_id=batch_id + WHERE initiated_outgoing_batch_id IS NULL + RETURNING amount + LOOP + SELECT sum.val, sum.frac + INTO local_sum.val, local_sum.frac + FROM amount_add(local_sum, tx.amount) AS sum; + END LOOP; + -- Update the batch with the sum of amounts + UPDATE initiated_outgoing_batches SET sum=local_sum WHERE initiated_outgoing_batch_id=batch_id; +END IF; +END $$; + +CREATE FUNCTION batch_status_update( + IN in_message_id text, + IN in_status submission_state, + IN in_status_msg text +) +RETURNS void +LANGUAGE plpgsql AS $$ +DECLARE +local_batch_id INT8; +BEGIN + -- Check if there is a batch for this message id + SELECT initiated_outgoing_batch_id INTO local_batch_id + FROM initiated_outgoing_batches + WHERE message_id = in_message_id; + IF FOUND THEN + -- Update unsettled batch status + UPDATE initiated_outgoing_batches + SET status = in_status, status_msg = in_status_msg + WHERE initiated_outgoing_batch_id = local_batch_id + AND status NOT IN ('success', 'permanent_failure', 'late_failure'); + + -- When a batch succeed it doesn't mean that individual transaction also succeed + IF in_status = 'success' THEN + in_status = 'pending'; + END IF; + + -- Update unsettled batch's transaction status + UPDATE initiated_outgoing_transactions + SET status = in_status, status_msg = in_status_msg + WHERE initiated_outgoing_batch_id = local_batch_id + AND status NOT IN ('success', 'permanent_failure', 'late_failure'); + END IF; +END $$; + +CREATE FUNCTION tx_status_update( + IN in_end_to_end_id text, + IN in_message_id text, + IN in_status submission_state, + IN in_status_msg text +) +RETURNS void +LANGUAGE plpgsql AS $$ +DECLARE +local_status submission_state; +local_tx_id INT8; +BEGIN + -- Check current tx status + SELECT initiated_outgoing_transaction_id, status INTO local_tx_id, local_status + FROM initiated_outgoing_transactions + WHERE end_to_end_id = in_end_to_end_id; + IF FOUND THEN + -- Update unsettled transaction status + IF local_status = 'success' AND in_status = 'permanent_failure' THEN + UPDATE initiated_outgoing_transactions + SET status = 'late_failure', status_msg = in_status_msg + WHERE initiated_outgoing_transaction_id = local_tx_id; + ELSIF local_status NOT IN ('success', 'permanent_failure', 'late_failure') THEN + UPDATE initiated_outgoing_transactions + SET status = in_status, status_msg = in_status_msg + WHERE initiated_outgoing_transaction_id = local_tx_id; + END IF; + + -- Update unsettled batch status + UPDATE initiated_outgoing_batches + SET status = 'success', status_msg = NULL + WHERE message_id = in_message_id + AND status NOT IN ('success', 'permanent_failure', 'late_failure'); + END IF; +END $$; +\ No newline at end of file diff --git a/nexus/build.gradle b/nexus/build.gradle @@ -63,5 +63,7 @@ shadowJar { exclude(dependency("io.ktor:ktor-client-cio:.*")) // Crypto exclude(dependency("org.bouncycastle:.*")) + // CLI + exclude(dependency("com.github.ajalt.mordant:mordant:.*")) } } \ No newline at end of file diff --git a/nexus/codegen.py b/nexus/codegen.py @@ -62,7 +62,7 @@ def iso20022codegenExternalCodeSet(): // THIS FILE IS GENERATED, DO NOT EDIT -package tech.libeufin.nexus +package tech.libeufin.nexus.iso20022 {extractCodeSet("ExternalStatusReason1Code", "ExternalStatusReasonCode")} @@ -74,7 +74,7 @@ package tech.libeufin.nexus """ with open( - "src/main/kotlin/tech/libeufin/nexus/Iso20022ExternalCodeSets.kt", "w" + "src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt", "w" ) as file1: file1.write(kt) @@ -139,7 +139,7 @@ def iso20022codegenBankTransactionCode(): // THIS FILE IS GENERATED, DO NOT EDIT -package tech.libeufin.nexus +package tech.libeufin.nexus.iso20022 {extractCodeSet("Domain", "ExternalBankTransactionDomainCode")} @@ -149,7 +149,7 @@ package tech.libeufin.nexus """ with open( - "src/main/kotlin/tech/libeufin/nexus/Iso20022BankTransactionCode.kt", "w" + "src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt", "w" ) as file1: file1.write(kt) diff --git a/nexus/conf/gls.conf b/nexus/conf/gls.conf @@ -0,0 +1,19 @@ +[nexus-ebics] +CURRENCY = EUR + +HOST_BASE_URL = https://ebics.multivia-suite.de/ebicsweb/ebicsweb +BANK_DIALECT = gls + +BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json +CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json + +HOST_ID = PFEBICS +USER_ID = PFC00563 +PARTNER_ID = PFC00563 + +IBAN = DE89500105171325381664 +BIC = BIC +NAME = myname + +[libeufin-nexusdb-postgres] +CONFIG = postgres:///libeufincheck +\ No newline at end of file diff --git a/nexus/sample/platform/gls_camt052.xml b/nexus/sample/platform/gls_camt052.xml @@ -1,314 +1,727 @@ <?xml version="1.0" encoding="UTF-8"?> <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.02" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.052.001.02 camt.052.001.02.xsd"> - <BkToCstmrAcctRpt> - <Rpt> - <Ntry> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.052.001.02 camt.052.001.02.xsd"> + <BkToCstmrAcctRpt> + <Rpt> + <Ntry> + <Amt Ccy="EUR">2.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-18</Dt> + </BookgDt> + <AcctSvcrRef>2024041801514102000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>COMPAT_SUCCESS</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>2024041785403105090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">2.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-18</Dt> - </BookgDt> - <AcctSvcrRef>2024041801514102000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <MsgId>G059N0SR5V0WZ0XSFY1H92QBZ0</MsgId> - <PmtInfId>NOTPROVIDED</PmtInfId> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>2024041785403105090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">2.00</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Mr Test</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>John Smith</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <CdtrAgt> - <FinInstnId> - <BIC>BYLADEM1WOR</BIC> - </FinInstnId> - </CdtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>TestABC123</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Mr Test</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>BYLADEM1WOR</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>TestABC123</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-05</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-05</Dt> + </ValDt> + <AcctSvcrRef>2024090509342698000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+159+00931</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>8XK8Z7RAX224FGWK832FD40GYC</EndToEndId> + <TxId>2024090455250415090200000010000003</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">1.10</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-18</Dt> - </BookgDt> - <ValDt> - <Dt>2024-04-18</Dt> - </ValDt> - <AcctSvcrRef>2024041810552821000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <MsgId>YF5QBARGQ0MNY0VK59S477VDG4</MsgId> - <PmtInfId>NOTPROVIDED</PmtInfId> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>2024041885917775090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">1.10</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Mr Test</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>John Smith</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <CdtrAgt> - <FinInstnId> - <BIC>INGDDEFFXXX</BIC> - </FinInstnId> - </CdtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>This should fail because dummy</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+159+00931</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE18500105173385245163</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RmtInf> + <Ustrd>Retoure SEPA </Ustrd> + <Ustrd>multi line</Ustrd> + </RmtInf> + <RtrInf> + <OrgnlBkTxCd> + <Prtry> + <Cd>116</Cd> + <Issr>DK</Issr> + </Prtry> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <BICOrBEI>GENODEM1GLS</BICOrBEI> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>AC01</Cd> + </Rsn> + <AddtlInf>IBAN fehlerhaft und ungültig</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Retouren</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-12</Dt> + </BookgDt> + <AcctSvcrRef>2024041210041357000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>BYLADEM1WOR-G2910276709458A2</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">3.00</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-12</Dt> - </BookgDt> - <AcctSvcrRef>2024041210041357000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>BYLADEM1WOR-G2910276709458A2</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">3.00</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>John Smith</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>Mr Test</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BIC>BYLADEM1WOR</BIC> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>John Smith</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Mr Test</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <DbtrAgt> + <FinInstnId> + <BIC>BYLADEM1WOR</BIC> + </FinInstnId> + </DbtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-12</Dt> + </BookgDt> + <AcctSvcrRef>2024041210041357000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>COMPAT_FAILURE</EndToEndId> + <TxId>2024042288942205090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">1.10</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-12</Dt> - </BookgDt> - <AcctSvcrRef>2024041210041357000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>RRTN</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <EndToEndId>G27KNKZAR5DV7HRB085YMA9GB4</EndToEndId> - <TxId>2024042288942205090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">1.10</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>RRTN</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>John Smith</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>Mr Test</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RtrInf> - <OrgnlBkTxCd> - <Prtry> - <Cd>116</Cd> - <Issr>DK</Issr> - </Prtry> - </OrgnlBkTxCd> - <Orgtr> - <Id> - <OrgId> - <BICOrBEI>GENODEM1GLS</BICOrBEI> - </OrgId> - </Id> - </Orgtr> - <Rsn> - <Cd>AC01</Cd> - </Rsn> - <AddtlInf>IBAN ...</AddtlInf> - </RtrInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> - </Ntry> - </Rpt> - </BkToCstmrAcctRpt> -</Document> - -\ No newline at end of file + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>John Smith</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Mr Test</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Prtry> + <Cd>116</Cd> + <Issr>DK</Issr> + </Prtry> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <BICOrBEI>GENODEM1GLS</BICOrBEI> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>AC01</Cd> + </Rsn> + <AddtlInf>IBAN ...</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-02</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-02</Dt> + </ValDt> + <AcctSvcrRef>2024090216552232000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>BATCH_SINGLE_SUCCESS</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>FD622SMXKT5QWSAHDY0H8NYG3G</EndToEndId> + <TxId>2024090252501131090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">1.10</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Grothoff Hans</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE89500105173198527518</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>GENODEM1GLS</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>single 2024-09-02T14:29:52.875253314Z</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-18</Dt> + </BookgDt> + <ValDt> + <Dt>2024-04-18</Dt> + </ValDt> + <AcctSvcrRef>2024041810552821000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>YF5QBARGQ0MNY0VK59S477VDG4</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>2024041885917775090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">1.10</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Mr Test</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>INGDDEFFXXX</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Simple tx</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">0.46</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-20</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-20</Dt> + </ValDt> + <AcctSvcrRef>2024092019251584000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+191+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>BATCH_MANY_SUCCESS</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">0.46</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+191+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + </RltdPties> + <RmtInf> + <Ustrd>SEPA Sammel-Ueberweisung mit 4 Ueberweisungen MSG-ID: BATCH_MANY_SUCCESS</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Sammelüberweisung</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">0.42</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-23</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-23</Dt> + </ValDt> + <AcctSvcrRef>2024092100252498000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>BATCH_SINGLE_RETURN</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5</EndToEndId> + <TxId>2024092374955203090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">0.42</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE18500105173385245163</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>INGDDEFFXXX</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>This should fail because bad iban</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">0.42</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-24</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-24</Dt> + </ValDt> + <AcctSvcrRef>2024092409341766000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+159+00931</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5</EndToEndId> + <TxId>2024092374955203090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">0.42</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+159+00931</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE18500105173385245163</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RmtInf> + <Ustrd>Retoure ...</Ustrd> + </RmtInf> + <RtrInf> + <OrgnlBkTxCd> + <Prtry> + <Cd>116</Cd> + <Issr>DK</Issr> + </Prtry> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <BICOrBEI>GENODEM1GLS</BICOrBEI> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>AC01</Cd> + </Rsn> + <AddtlInf>IBAN fehlerhaft und ungültig</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Retouren</AddtlNtryInf> + </Ntry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> +\ No newline at end of file diff --git a/nexus/sample/platform/gls_camt053.xml b/nexus/sample/platform/gls_camt053.xml @@ -1,321 +1,549 @@ <?xml version="1.0" encoding="UTF-8"?> <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02 camt.053.001.02.xsd"> - <BkToCstmrStmt> - <Stmt> - <Ntry> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02 camt.053.001.02.xsd"> + <BkToCstmrStmt> + <Stmt> + <Ntry> + <Amt Ccy="EUR">2.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-18</Dt> + </BookgDt> + <AcctSvcrRef>2024041801514102000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>COMPAT_SUCCESS</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>2024041785403105090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">2.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-18</Dt> - </BookgDt> - <AcctSvcrRef>2024041801514102000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <MsgId>G059N0SR5V0WZ0XSFY1H92QBZ0</MsgId> - <PmtInfId>NOTPROVIDED</PmtInfId> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>2024041785403105090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">2.00</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Mr Test</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>John Smith</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <CdtrAgt> - <FinInstnId> - <BIC>BYLADEM1WOR</BIC> - </FinInstnId> - </CdtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>TestABC123</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Mr Test</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>BYLADEM1WOR</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>TestABC123</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-04</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-04</Dt> + </ValDt> + <AcctSvcrRef>2024090413252540000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>ACMT</Cd> + <Fmly> + <Cd>ACOP</Cd> + <SubFmlyCd>PSTE</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+899+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>KGTDBASWTJ6JM89WXD3Q5KFQC4</EndToEndId> + <TxId>2024090455250415090200000010000002</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">1.10</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-18</Dt> - </BookgDt> - <ValDt> - <Dt>2024-04-18</Dt> - </ValDt> - <AcctSvcrRef>2024041810552821000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <MsgId>YF5QBARGQ0MNY0VK59S477VDG4</MsgId> - <PmtInfId>NOTPROVIDED</PmtInfId> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>2024041885917775090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">1.10</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - <Prtry> - <Cd>NTRF+177+08381</Cd> - <Issr>DK</Issr> - </Prtry> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Mr Test</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>John Smith</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <CdtrAgt> - <FinInstnId> - <BIC>INGDDEFFXXX</BIC> - </FinInstnId> - </CdtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>This should fail because dummy</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>ACMT</Cd> + <Fmly> + <Cd>ACOP</Cd> + <SubFmlyCd>PSTE</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NRTI+899+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE54430609674049078800</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Florian Dold</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <DbtrAgt> + <FinInstnId> + <BIC>GENODEM1GLS</BIC> + </FinInstnId> + </DbtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Retoure aus SEPA Überweisung</Ustrd> + <Ustrd> multi line</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Storno</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3.30</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-04</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-04</Dt> + </ValDt> + <AcctSvcrRef>2024090413252541000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+191+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>BATCH_MANY_PART</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">3.30</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+191+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + </RltdPties> + <RmtInf> + <Ustrd>SEPA Sammel-Ueberweisung mit 3 Ueberweisungen MSG-ID: IP5QN7GOBZDJLKXDGQGD5AYS3WLSBEIY6U</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Sammelüberweisung</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-12</Dt> + </BookgDt> + <AcctSvcrRef>2024041210041357000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>BYLADEM1WOR-G2910276709458A2</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">3.00</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-12</Dt> - </BookgDt> - <AcctSvcrRef>2024041210041357000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <EndToEndId>NOTPROVIDED</EndToEndId> - <TxId>BYLADEM1WOR-G2910276709458A2</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">3.00</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>ESCT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>John Smith</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>Mr Test</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BIC>BYLADEM1WOR</BIC> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Ustrd>Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-</Ustrd> - </RmtInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> - </Ntry> - <Ntry> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>John Smith</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Mr Test</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <DbtrAgt> + <FinInstnId> + <BIC>BYLADEM1WOR</BIC> + </FinInstnId> + </DbtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-12</Dt> + </BookgDt> + <AcctSvcrRef>2024041210041357000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <EndToEndId>COMPAT_FAILURE</EndToEndId> + <TxId>2024042288942205090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> <Amt Ccy="EUR">1.10</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2024-04-12</Dt> - </BookgDt> - <AcctSvcrRef>2024041210041357000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>RRTN</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <EndToEndId>G27KNKZAR5DV7HRB085YMA9GB4</EndToEndId> - <TxId>2024042288942205090200000010000001</TxId> - </Refs> - <AmtDtls> - <TxAmt> - <Amt Ccy="EUR">1.10</Amt> - </TxAmt> - </AmtDtls> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>RRTN</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>John Smith</Nm> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>DE84500105177118117964</IBAN> - </Id> - </DbtrAcct> - <Cdtr> - <Nm>Mr Test</Nm> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>DE20500105172419259181</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BIC>BYLADEM1WOR</BIC> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RtrInf> - <OrgnlBkTxCd> - <Prtry> - <Cd>116</Cd> - <Issr>DK</Issr> - </Prtry> - </OrgnlBkTxCd> - <Orgtr> - <Id> - <OrgId> - <BICOrBEI>GENODEM1GLS</BICOrBEI> - </OrgId> - </Id> - </Orgtr> - <Rsn> - <Cd>AC01</Cd> - </Rsn> - <AddtlInf>IBAN ...</AddtlInf> - </RtrInf> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> - </Ntry> - </Stmt> - </BkToCstmrStmt> -</Document> - -\ No newline at end of file + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>John Smith</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Mr Test</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <DbtrAgt> + <FinInstnId> + <BIC>BYLADEM1WOR</BIC> + </FinInstnId> + </DbtrAgt> + </RltdAgts> + <RtrInf> + <OrgnlBkTxCd> + <Prtry> + <Cd>116</Cd> + <Issr>DK</Issr> + </Prtry> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <BICOrBEI>GENODEM1GLS</BICOrBEI> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>AC01</Cd> + </Rsn> + <AddtlInf>IBAN ...</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsgutschr.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-09-02</Dt> + </BookgDt> + <ValDt> + <Dt>2024-09-02</Dt> + </ValDt> + <AcctSvcrRef>2024090216552232000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>BATCH_SINGLE_SUCCESS</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>FD622SMXKT5QWSAHDY0H8NYG3G</EndToEndId> + <TxId>2024090252501131090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">1.10</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Florian Dold</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE89500105171325381664</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>Grothoff Hans</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE89500105173198527518</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>GENODEM1GLS</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>single 2024-09-02T14:29:52.875253314Z</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2024-04-18</Dt> + </BookgDt> + <ValDt> + <Dt>2024-04-18</Dt> + </ValDt> + <AcctSvcrRef>2024041810552821000</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>YF5QBARGQ0MNY0VK59S477VDG4</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + <TxId>2024041885917775090200000010000001</TxId> + </Refs> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">1.10</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>NTRF+177+08381</Cd> + <Issr>DK</Issr> + </Prtry> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Mr Test</Nm> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DE84500105177118117964</IBAN> + </Id> + </DbtrAcct> + <Cdtr> + <Nm>John Smith</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>DE20500105172419259181</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BIC>INGDDEFFXXX</BIC> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Simple tx</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>Überweisungsauftrag</AddtlNtryInf> + </Ntry> + </Stmt> + </BkToCstmrStmt> +</Document> +\ No newline at end of file diff --git a/nexus/sample/platform/gls_pain001.xml b/nexus/sample/platform/gls_pain001.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> +\ No newline at end of file diff --git a/nexus/sample/platform/hac.xml b/nexus/sample/platform/hac.xml @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document + xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03 pain.002.001.03.xsd" + xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <CstmrPmtStsRpt> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>FILE_DOWNLOAD</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>2024-09-02T15:47:30.350Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>TS01</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>FILE_UPLOAD</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_SUCCESS</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-09-02T20:48:43.153Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>TS01</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>ES_VERIFICATION</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_SUCCESS</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-09-02T20:48:43.153Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>DS01</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>ORDER_HAC_FINAL_POS</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_SUCCESS</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-09-02T20:48:43.153Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <AddtlInf>Some multiline info</AddtlInf> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>FILE_DOWNLOAD</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>2024-09-02T15:47:31.754Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>TD01</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>FILE_UPLOAD</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_FAILURE</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-08-23T15:34:11.987Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>TS01</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>ES_VERIFICATION</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_FAILURE</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-08-23T15:34:13.307Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>TD03</Cd> + </Rsn> + </StsRsnInf> + </OrgnlPmtInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>ORDER_HAC_FINAL_NEG</OrgnlPmtInfId> + <StsRsnInf> + <Orgtr> + <Id> + <OrgId> + <Othr> + <Id>ORDER_FAILURE</Id> + <SchmeNm> + <Prtry>OrderID</Prtry> + </SchmeNm> + </Othr> + <Othr> + <Id>2024-08-23T15:34:13.307Z</Id> + <SchmeNm> + <Prtry>TimeStamp</Prtry> + </SchmeNm> + </Othr> + </OrgId> + </Id> + </Orgtr> + </StsRsnInf> + </OrgnlPmtInfAndSts> + </CstmrPmtStsRpt> +</Document> +\ No newline at end of file diff --git a/nexus/sample/platform/pain002.xml b/nexus/sample/platform/pain002.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.10" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.002.001.10 pain.002.001.10.xsd"> + <CstmrPmtStsRpt> + <OrgnlGrpInfAndSts> + <OrgnlMsgId>05BD4C5B4A2649B5B08F6EF6A31F197A</OrgnlMsgId> + <GrpSts>PART</GrpSts> + </OrgnlGrpInfAndSts> + <OrgnlPmtInfAndSts> + <OrgnlPmtInfId>NOTPROVIDED</OrgnlPmtInfId> + <PmtInfSts>PART</PmtInfSts> + <StsRsnInf> + <Rsn> + <Cd>DT06</Cd> + </Rsn> + <AddtlInf>Due date is not a working day. Order will be executed on the next working day</AddtlInf> + </StsRsnInf> + <TxInfAndSts> + <OrgnlInstrId>AQCXNCPWD8PHW5JTN65Y5XTF7R</OrgnlInstrId> + <OrgnlEndToEndId>AQCXNCPWD8PHW5JTN65Y5XTF7R</OrgnlEndToEndId> + <TxSts>RJCT</TxSts> + <StsRsnInf> + <Rsn> + <Cd>AC04</Cd> + </Rsn> + <AddtlInf>Error message</AddtlInf> + </StsRsnInf> + </TxInfAndSts> + <TxInfAndSts> + <OrgnlInstrId>EE9SX76FC5YSC657EK3GMVZ9TC</OrgnlInstrId> + <OrgnlEndToEndId>EE9SX76FC5YSC657EK3GMVZ9TC</OrgnlEndToEndId> + <TxSts>RJCT</TxSts> + <StsRsnInf> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + <AddtlInf>Error message</AddtlInf> + </StsRsnInf> + </TxInfAndSts> + <TxInfAndSts> + <OrgnlInstrId>V5B3MXPEWES9VQW1JDRD6VAET4</OrgnlInstrId> + <OrgnlEndToEndId>V5B3MXPEWES9VQW1JDRD6VAET4</OrgnlEndToEndId> + <TxSts>RJCT</TxSts> + <StsRsnInf> + <Rsn> + <Cd>RR02</Cd> + </Rsn> + <AddtlInf>Error message</AddtlInf> + </StsRsnInf> + </TxInfAndSts> + </OrgnlPmtInfAndSts> + </CstmrPmtStsRpt> +</Document> +\ No newline at end of file diff --git a/nexus/sample/platform/postfinance_camt053.xml b/nexus/sample/platform/postfinance_camt053.xml @@ -104,6 +104,48 @@ </TxDtls> </NtryDtls> </Ntry> + <Ntry> + <Amt Ccy="CHF">406.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2024-08-26</Dt> + </BookgDt> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>EB4D22D428214261B2B3012D2A8CEC36</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <UETR>fe4ba22a-8fc4-4f9b-80fc-12c4157a90bc</UETR> + </Refs> + <Amt Ccy="CHF">406.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>EZAG ISO 20022 BULK ORDER E-FINANCE NOTPROVIDED + EB4D22D428214261B2B3012D2A8CEC36</AddtlNtryInf> + </Ntry> </Stmt> </BkToCstmrStmt> </Document> \ No newline at end of file diff --git a/nexus/sample/platform/postfinance_camt054.xml b/nexus/sample/platform/postfinance_camt054.xml @@ -170,6 +170,37 @@ </NtryDtls> <AddtlNtryInf>RETOURE IHRER ZAHLUNG VOM 15.01.2024 ... GRUND: KEINE UEBEREINSTIMMUNG VON KONTONUMMER UND KONTOINHABER</AddtlNtryInf> </Ntry> + <Ntry> + <Amt Ccy="CHF">406.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2024-01-15</Dt> + </BookgDt> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>ZS1PGNTSV0ZNDFAJBBWWB8015G</MsgId> + <PmtInfId>NOTPROVIDED</PmtInfId> + <UETR>c810f027-08f8-44ad-bf53-647ae3fc349f</UETR> + </Refs> + <Amt Ccy="CHF">406.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TxDtls> + </NtryDtls> + </Ntry> </Ntfctn> </BkToCstmrDbtCdtNtfctn> </Document> \ No newline at end of file diff --git a/nexus/sample/platform/postfinance_pain001.xml b/nexus/sample/platform/postfinance_pain001.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"><CstmrCdtTrfInitn><GrpHdr><MsgId>MESSAGE_ID</MsgId><CreDtTm>2024-09-09T00:00:00Z</CreDtTm><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><InitgPty><Nm>myname</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>NOTPROVIDED</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>false</BtchBookg><NbOfTxs>3</NbOfTxs><CtrlSum>47.32</CtrlSum><PmtTpInf><SvcLvl><Cd>SDVA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>2024-09-09Z</Dt></ReqdExctnDt><Dbtr><Nm>myname</Nm></Dbtr><DbtrAcct><Id><IBAN>CH7789144474425692816</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>BIC</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><InstrId>TX_FIRST</InstrId><EndToEndId>TX_FIRST</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">42</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 42</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_SECOND</InstrId><EndToEndId>TX_SECOND</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">5.11</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 5.11</Ustrd></RmtInf></CdtTrfTxInf><CdtTrfTxInf><PmtId><InstrId>TX_THIRD</InstrId><EndToEndId>TX_THIRD</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">0.21</InstdAmt></Amt><Cdtr><Nm>Test</Nm></Cdtr><CdtrAcct><Id><IBAN>CH4189144589712575493</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Test 0.21</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document> +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsLogger.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsLogger.kt @@ -63,7 +63,7 @@ class EbicsLogger(private val dir: Path?) { } companion object { - private val TIME_WITH_MS = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); + private val TIME_WITH_MS = DateTimeFormatter.ofPattern("HH:mm:ss.SSS") } } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt @@ -1,682 +0,0 @@ -/* - * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. - - * LibEuFin is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation; either version 3, or - * (at your option) any later version. - - * LibEuFin is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General - * Public License for more details. - - * You should have received a copy of the GNU Affero General Public - * License along with LibEuFin; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/> - */ -package tech.libeufin.nexus - -import tech.libeufin.common.IbanPayto -import tech.libeufin.common.TalerAmount -import tech.libeufin.nexus.ebics.Dialect -import java.io.InputStream -import java.time.Instant -import java.time.ZoneId -import java.time.ZoneOffset -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter - -/** String representation of a Taler [amount] compatible with EBICS */ -fun getAmountNoCurrency(amount: TalerAmount): String { - if (amount.isSubCent()) { - throw Exception("Sub-cent amounts not supported") - } - return amount.number().toString() -} - -/** Create a pain.001 XML document valid for [dialect] */ -fun createPain001( - requestUid: String, - initiationTimestamp: Instant, - debitAccount: IbanAccountMetadata, - amount: TalerAmount, - wireTransferSubject: String, - creditAccount: IbanAccountMetadata, - dialect: Dialect -): ByteArray { - val version = "09" - val zonedTimestamp = ZonedDateTime.ofInstant(initiationTimestamp, ZoneId.of("UTC")) - val amountWithoutCurrency: String = getAmountNoCurrency(amount) - return XmlBuilder.toBytes("Document") { - attr("xmlns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version") - attr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") - attr("xsi:schemaLocation", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version pain.001.001.$version.xsd") - el("CstmrCdtTrfInitn") { - el("GrpHdr") { - // Use for idempotency as banks will refuse to process EBICS request with the same MsgId for a pre- agreed period - // This is especially important for bounces - el("MsgId", requestUid) - el("CreDtTm", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(zonedTimestamp)) - el("NbOfTxs", "1") - el("CtrlSum", amountWithoutCurrency) - el("InitgPty/Nm", debitAccount.name) - } - el("PmtInf") { - el("PmtInfId", "NOTPROVIDED") - el("PmtMtd", "TRF") - el("BtchBookg", "false") - el("NbOfTxs", "1") - el("CtrlSum", amountWithoutCurrency) - el("PmtTpInf/SvcLvl/Cd", - when (dialect) { - Dialect.postfinance -> "SDVA" - Dialect.gls -> "SEPA" - } - ) - el("ReqdExctnDt/Dt", DateTimeFormatter.ISO_DATE.format(zonedTimestamp)) - el("Dbtr/Nm", debitAccount.name) - el("DbtrAcct/Id/IBAN", debitAccount.iban) - el("DbtrAgt/FinInstnId") { - if (debitAccount.bic != null) { - el("BICFI", debitAccount.bic) - } else { - el("Othr/Id", "NOTPROVIDED") - } - } - el("ChrgBr", "SLEV") - el("CdtTrfTxInf") { - el("PmtId") { - el("InstrId", "NOTPROVIDED") - // Used to identify this transaction in CAMT files when MsgId is not present - el("EndToEndId", requestUid) - } - el("Amt/InstdAmt") { - attr("Ccy", amount.currency) - text(amountWithoutCurrency) - } - if (creditAccount.bic != null) el("CdtrAgt/FinInstnId/BICFI", creditAccount.bic) - el("Cdtr") { - el("Nm", creditAccount.name) - // Addr might become a requirement in the future - /*el("PstlAdr") { - el("TwnNm", "Bochum") - el("Ctry", "DE") - }*/ - } - el("CdtrAcct/Id/IBAN", creditAccount.iban) - el("RmtInf/Ustrd", wireTransferSubject) - } - } - } - } -} - -data class CustomerAck( - val actionType: HacAction, - val orderId: String?, - val code: ExternalStatusReasonCode?, - val info: String, - val timestamp: Instant -) { - fun msg(): String = buildString { - append("$actionType") - if (code != null) append(" ${code.isoCode}") - append(" - '${actionType.description}'") - if (code != null) append(" '${code.description}'") - if (info != "") append(" - '$info'") - } - - override fun toString(): String = buildString { - append(timestamp.fmtDateTime()) - if (orderId != null) append(" $orderId") - append(" ${msg()}") - } -} - -/** Parse HAC pain.002 XML file */ -fun parseCustomerAck(xml: InputStream): List<CustomerAck> { - return XmlDestructor.fromStream(xml, "Document") { - one("CstmrPmtStsRpt").map("OrgnlPmtInfAndSts") { - val actionType = one("OrgnlPmtInfId").enum<HacAction>() - one("StsRsnInf") { - var timestamp: Instant? = null - var orderId: String? = null - one("Orgtr").one("Id").one("OrgId").each("Othr") { - val value = one("Id") - val key = one("SchmeNm").one("Prtry").text() - when (key) { - "TimeStamp" -> { - timestamp = value.dateTime().toInstant(ZoneOffset.UTC) - } - "OrderID" -> orderId = value.text() - // TODO extract ids ? - } - } - val code = opt("Rsn")?.one("Cd")?.enum<ExternalStatusReasonCode>() - val info = map("AddtlInf") { text() }.joinToString("") - CustomerAck(actionType, orderId, code, info, timestamp!!) - } - } - } -} - -data class PaymentStatus( - val msgId: String, - val paymentId: String?, - val txId: String?, - val paymentCode: ExternalPaymentGroupStatusCode, - val txCode: ExternalPaymentTransactionStatusCode?, - val reasons: List<Reason> -) { - fun id(): String { - var str = msgId - if (paymentId != null) str += ".$paymentId" - if (txId != null) str += ".$txId" - return str - } - - fun code(): String = txCode?.isoCode ?: paymentCode.isoCode - - fun description(): String = txCode?.description ?: paymentCode.description - - fun msg(): String { - return if (reasons.isEmpty()) { - "${code()} '${description()}'" - } else if (reasons.size == 1) { - "${code()} ${reasons[0].code.isoCode} - '${description()}' '${reasons[0].code.description}'" - } else { - buildString { - append("${code()} '${description()}' - ") - for (reason in reasons) { - append("${reason.code.isoCode} '${reason.code.description}' ") - } - } - } - } - - override fun toString(): String = "${id()} ${msg()}" -} - -data class Reason ( - val code: ExternalStatusReasonCode, - val information: String -) - -/** Parse pain.002 XML file */ -fun parseCustomerPaymentStatusReport(xml: InputStream): PaymentStatus { - fun XmlDestructor.reasons(): List<Reason> { - return map("StsRsnInf") { - val code = one("Rsn").one("Cd").enum<ExternalStatusReasonCode>() - // TODO parse information - Reason(code, "") - } - } - return XmlDestructor.fromStream(xml, "Document") { - // TODO handle batch status - one("CstmrPmtStsRpt") { - val (msgId, msgCode, msgReasons) = one("OrgnlGrpInfAndSts") { - val id = one("OrgnlMsgId").text() - val code = opt("GrpSts")?.enum<ExternalPaymentGroupStatusCode>() - val reasons = reasons() - Triple(id, code, reasons) - } - opt("OrgnlPmtInfAndSts") { - val payId = one("OrgnlPmtInfId").text() - val payCode = one("PmtInfSts").enum<ExternalPaymentGroupStatusCode>() - val payReasons = reasons() - opt("TxInfAndSts") { - val txId = one("OrgnlInstrId").text() - val txCode = one("TxSts").enum<ExternalPaymentTransactionStatusCode>() - val txReasons = reasons() - PaymentStatus(msgId, payId, txId, payCode, txCode, txReasons) - } ?: PaymentStatus(msgId, payId, null, payCode, null, payReasons) - } ?: PaymentStatus(msgId, null, null, msgCode!!, null, msgReasons) - } - } -} - -sealed interface TxNotification { - val executionTime: Instant - data class Reversal( - val msgId: String, - val reason: String?, - override val executionTime: Instant - ): TxNotification -} - -/** ISO20022 incoming payment */ -data class IncomingPayment( - /** ISO20022 UETR & TxID */ - val bankId: String? = null, // Null when TxID is wrong with Atruvia's implementation of instant transactions - val amount: TalerAmount, - val wireTransferSubject: String, - override val executionTime: Instant, - val debitPaytoUri: String -): TxNotification { - override fun toString(): String { - return "IN ${executionTime.fmtDate()} $amount '$bankId' debitor=$debitPaytoUri subject=\"$wireTransferSubject\"" - } -} - -/** ISO20022 outgoing payment */ -data class OutgoingPayment( - /** ISO20022 MessageIdentification & EndToEndId */ - val messageId: String, - val amount: TalerAmount, - val wireTransferSubject: String? = null, // Some implementation does not provide this for recovery - override val executionTime: Instant, - val creditPaytoUri: String? = null // Some implementation does not provide this for recovery -): TxNotification { - override fun toString(): String { - return "OUT ${executionTime.fmtDate()} $amount '$messageId' creditor=$creditPaytoUri subject=\"$wireTransferSubject\"" - } -} - -private fun XmlDestructor.payto(prefix: String): String? { - val iban = opt("${prefix}Acct")?.one("Id")?.one("IBAN")?.text() - return if (iban != null) { - val name = opt(prefix) { opt("Nm")?.text() ?: opt("Pty")?.one("Nm")?.text() } - // Parse bic ? - IbanPayto.build(iban, null, name) - } else { - null - } -} - -private class TxErr(val msg: String): Exception(msg) - -private enum class Kind { - CRDT, - DBIT -} - -/** Parse camt.054 or camt.053 file */ -fun parseTx( - notifXml: InputStream, - acceptedCurrency: String, - dialect: Dialect -): List<TxNotification> { - /* - In ISO 20022 specifications, most fields are optional and the same information - can be written several times in different places. For libeufin, we're only - interested in a subset of the available values that can be found in both camt.052, - camt.053 and camt.054. This function should not fail on legitimate files and should - simply warn when available information are insufficient. - - EBICS and ISO20022 do not provide a perfect transaction identifier. The best is the - UETR (unique end-to-end transaction reference), which is a universally unique - identifier (UUID). However, it is not supplied by all banks. TxId (TransactionIdentification) - is a unique identification as assigned by the first instructing agent. As its format - is ambiguous, its uniqueness is not guaranteed by the standard, and it is only - supposed to be unique for a “pre-agreed period”, whatever that means. These two - identifiers are optional in the standard, but have the advantage of being unique - and can be used to track a transaction between banks so we use them when available. - - It is also possible to use AccountServicerReference, which is a unique reference - assigned by the account servicing institution. They can be present at several levels - (batch level, transaction level, etc.) and are often optional. They also have the - disadvantage of being known only by the account servicing institution. They should - therefore only be used as a last resort. - */ - - /** Check if a transaction status is BOOK */ - fun XmlDestructor.isBooked(): Boolean { - // We check at the Sts or Sts/Cd level for retrocompatibility - return one("Sts") { - val status = opt("Cd")?.text() ?: text() - status == "BOOK" - } - } - - /** Parse the instruction execution date */ - fun XmlDestructor.executionDate(): Instant { - // Value date if present else booking date - val date = opt("ValDt") ?: one("BookgDt") - val parsed = date.opt("Dt") { - date().atStartOfDay() - } ?: date.one("DtTm") { - dateTime() - } - return parsed.toInstant(ZoneOffset.UTC) - } - - /** Parse original transaction ID generated by libeufin-nexus */ - fun XmlDestructor.nexusId(): String? = - // We check at the EndToEndId or MsgId level for retrocompatibility - opt("Refs") { opt("EndToEndId")?.textProvided() ?: opt("MsgId")?.text() } - - /** Parse and format transaction return reasons */ - fun XmlDestructor.returnReason(): String = one("RtrInf") { - val code = one("Rsn").one("Cd").enum<ExternalReturnReasonCode>() - val info = opt("AddtlInf")?.text() - buildString { - append("${code.isoCode} '${code.description}'") - if (info != null) { - append(" - '$info'") - } - } - } - - /** Parse amount */ - fun XmlDestructor.amount(acceptedCurrency: String) = one("Amt") { - val currency = attr("Ccy") - /** FIXME: test by sending non-CHF to PoFi and see which currency gets here. */ - if (currency != acceptedCurrency) throw Exception("Currency $currency not supported") - TalerAmount("$currency:${text()}") - } - - /** Parse bank transaction code */ - fun XmlDestructor.bankTransactionCode(): BankTransactionCode { - return one("BkTxCd").one("Domn") { - val domain = one("Cd").enum<ExternalBankTransactionDomainCode>() - one("Fmly") { - val family = one("Cd").enum<ExternalBankTransactionFamilyCode>() - val subFamily = one("SubFmlyCd").enum<ExternalBankTransactionSubFamilyCode>() - - BankTransactionCode(domain, family, subFamily) - } - } - } - - val txsInfo = mutableListOf<TxInfo>() - - XmlDestructor.fromStream(notifXml, "Document") { when (dialect) { - Dialect.gls -> { - /** Common parsing logic for camt.052 and camt.053 */ - fun XmlDestructor.parseGlsInner() { - opt("Acct") { - // Sanity check on currency and IBAN ? - } - each("Ntry") { - if (!isBooked()) return@each - val entryRef = opt("AcctSvcrRef")?.text() - val bookDate = executionDate() - val kind = one("CdtDbtInd").enum<Kind>() - val amount = amount(acceptedCurrency) - one("NtryDtls").one("TxDtls") { // TODO handle batches - val code = bankTransactionCode() - if (!code.isPayment()) return@one - val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() - val nexusId = nexusId() - if (code.isReversal()) { - if (kind == Kind.CRDT) { - val reason = returnReason() - txsInfo.add(TxInfo.CreditReversal( - ref = nexusId ?: txRef ?: entryRef, - bookDate = bookDate, - nexusId = nexusId, - reason = reason, - code = code - )) - } - } else { - val subject = opt("RmtInf")?.map("Ustrd") { text() }?.joinToString("") - when (kind) { - Kind.CRDT -> { - val bankId = one("Refs").opt("TxId")?.text() - val debtorPayto = opt("RltdPties") { payto("Dbtr") } - txsInfo.add(TxInfo.Credit( - ref = bankId ?: txRef ?: entryRef, - bookDate = bookDate, - bankId = bankId, - amount = amount, - subject = subject, - debtorPayto = debtorPayto, - code = code - )) - } - Kind.DBIT -> { - val creditorPayto = opt("RltdPties") { payto("Cdtr") } - txsInfo.add(TxInfo.Debit( - ref = nexusId ?: txRef ?: entryRef, - bookDate = bookDate, - nexusId = nexusId, - amount = amount, - subject = subject, - creditorPayto = creditorPayto, - code = code - )) - } - } - } - } - } - } - opt("BkToCstmrStmt")?.each("Stmt") { // Camt.053 - // All transactions appear here the day after they are booked - parseGlsInner() - } - opt("BkToCstmrAcctRpt")?.each("Rpt") { // Camt.052 - // Transactions might appear here first before the end of the day - parseGlsInner() - } - opt("BkToCstmrDbtCdtNtfctn")?.each("Ntfctn") { // Camt.054 - // Instant transactions appear here a few seconds after being booked - opt("Acct") { - // Sanity check on currency and IBAN ? - } - each("Ntry") { - if (!isBooked()) return@each - val code = bankTransactionCode() - if (code.isReversal() || !code.isPayment()) return@each - val entryRef = opt("AcctSvcrRef")?.text() - val bookDate = executionDate() - val kind = one("CdtDbtInd").enum<Kind>() - val amount = amount(acceptedCurrency) - one("NtryDtls").one("TxDtls") { - val txRef = one("Refs").opt("AcctSvcrRef")?.text() - val subject = opt("RmtInf")?.map("Ustrd") { text() }?.joinToString("") - if (kind == Kind.CRDT) { - val bankId = one("Refs").opt("TxId")?.text() - val debtorPayto = opt("RltdPties") { payto("Dbtr") } - txsInfo.add(TxInfo.Credit( - ref = txRef ?: entryRef, - bookDate = bookDate, - // TODO use the bank ID again when Atruvia's implementation is fixed - bankId = null, - amount = amount, - subject = subject, - debtorPayto = debtorPayto, - code = code - )) - } - } - } - } - } - Dialect.postfinance -> { - opt("BkToCstmrStmt")?.each("Stmt") { // Camt.053 - /* - All transactions appear here on the day following their booking. Alas, some - necessary metadata is missing, which is only present in camt.054. However, - this file contains the structured return reasons that are missing from the - camt.054 files. That's why we only use this file for this purpose. - */ - opt("Acct") { - // Sanity check on currency and IBAN ? - } - each("Ntry") { - if (!isBooked()) return@each - val code = bankTransactionCode() - // Non reversal transaction are handled in camt.054 - if (!code.isReversal() || !code.isPayment()) return@each - - val entryRef = opt("AcctSvcrRef")?.text() - val bookDate = executionDate() - one("NtryDtls").one("TxDtls") { - val kind = one("CdtDbtInd").enum<Kind>() - if (kind == Kind.CRDT) { - val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() - val nexusId = nexusId() - val reason = returnReason() - txsInfo.add(TxInfo.CreditReversal( - ref = nexusId ?: txRef ?: entryRef, - bookDate = bookDate, - nexusId = nexusId, - reason = reason, - code = code - )) - } - } - } - } - opt("BkToCstmrDbtCdtNtfctn")?.each("Ntfctn") { // Camt.054 - // Instant transactions appear here a moment after being booked - opt("Acct") { - // Sanity check on currency and IBAN ? - } - each("Ntry") { - if (!isBooked()) return@each - val code = bankTransactionCode() - // Reversal are handled from camt.053 - if (code.isReversal() || !code.isPayment()) return@each - - val entryRef = opt("AcctSvcrRef")?.text() - val bookDate = executionDate() - one("NtryDtls").each("TxDtls") { - val kind = one("CdtDbtInd").enum<Kind>() - val amount = amount(acceptedCurrency) - val txRef = one("Refs").opt("AcctSvcrRef")?.text() - val subject = opt("RmtInf")?.map("Ustrd") { text() }?.joinToString("") - when (kind) { - Kind.CRDT -> { - val bankId = one("Refs").opt("UETR")?.text() - val debtorPayto = opt("RltdPties") { payto("Dbtr") } - txsInfo.add(TxInfo.Credit( - ref = bankId ?: txRef ?: entryRef, - bookDate = bookDate, - bankId = bankId, - amount = amount, - subject = subject, - debtorPayto = debtorPayto, - code = code - )) - } - Kind.DBIT -> { - val nexusId = nexusId() - val creditorPayto = opt("RltdPties") { payto("Cdtr") } - txsInfo.add(TxInfo.Debit( - ref = nexusId ?: txRef ?: entryRef, - bookDate = bookDate, - nexusId = nexusId, - amount = amount, - subject = subject, - creditorPayto = creditorPayto, - code = code - )) - } - } - } - } - } - } - }} - - return txsInfo.mapNotNull { - try { - parseTxLogic(it) - } catch (e: TxErr) { - // TODO: add more info in doc or in log message? - logger.warn("skip incomplete tx: ${e.msg}") - null - } - } -} - -private sealed interface TxInfo { - // Bank provider ref for debugging - val ref: String? - // When was this transaction booked - val bookDate: Instant - // ISO20022 bank transaction code - val code: BankTransactionCode - data class CreditReversal( - override val ref: String?, - override val bookDate: Instant, - override val code: BankTransactionCode, - // Unique ID generated by libeufin-nexus - val nexusId: String?, - val reason: String? - ): TxInfo - data class Credit( - override val ref: String?, - override val bookDate: Instant, - override val code: BankTransactionCode, - // Unique ID generated by payment provider - val bankId: String?, - val amount: TalerAmount, - val subject: String?, - val debtorPayto: String? - ): TxInfo - data class Debit( - override val ref: String?, - override val bookDate: Instant, - override val code: BankTransactionCode, - // Unique ID generated by libeufin-nexus - val nexusId: String?, - val amount: TalerAmount, - val subject: String?, - val creditorPayto: String? - ): TxInfo -} - -private fun parseTxLogic(info: TxInfo): TxNotification { - return when (info) { - is TxInfo.CreditReversal -> { - if (info.nexusId == null) - throw TxErr("missing nexus ID for Credit reversal ${info.ref}") - TxNotification.Reversal( - msgId = info.nexusId, - reason = info.reason, - executionTime = info.bookDate - ) - } - is TxInfo.Credit -> { - /*if (info.bankId == null) TODO use the bank ID again when Atruvia's implementation is fixed - throw TxErr("missing bank ID for Credit ${info.ref}")*/ - if (info.subject == null) - throw TxErr("missing subject for Credit ${info.ref}") - if (info.debtorPayto == null) - throw TxErr("missing debtor info for Credit ${info.ref}") - IncomingPayment( - amount = info.amount, - bankId = info.bankId, - debitPaytoUri = info.debtorPayto, - executionTime = info.bookDate, - wireTransferSubject = info.subject - ) - } - is TxInfo.Debit -> { - if (info.nexusId == null) - throw TxErr("missing nexus ID for Debit ${info.ref}") - OutgoingPayment( - amount = info.amount, - messageId = info.nexusId, - executionTime = info.bookDate, - creditPaytoUri = info.creditorPayto, - wireTransferSubject = info.subject - ) - } - } -} - -data class BankTransactionCode( - val domain: ExternalBankTransactionDomainCode, - val family: ExternalBankTransactionFamilyCode, - val subFamily: ExternalBankTransactionSubFamilyCode -) { - fun isReversal(): Boolean = REVERSAL_CODE.contains(subFamily) - fun isPayment(): Boolean = domain == ExternalBankTransactionDomainCode.PMNT - - override fun toString(): String = - "${domain.name} ${family.name} ${subFamily.name} - '${domain.description}' '${family.description}' '${subFamily.description}'" - - companion object { - private val REVERSAL_CODE = setOf( - ExternalBankTransactionSubFamilyCode.RPCR, - ExternalBankTransactionSubFamilyCode.RRTN, - ) - } -} -\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022BankTransactionCode.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022BankTransactionCode.kt @@ -1,386 +0,0 @@ -/* - * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. - - * LibEuFin is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation; either version 3, or - * (at your option) any later version. - - * LibEuFin is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General - * Public License for more details. - - * You should have received a copy of the GNU Affero General Public - * License along with LibEuFin; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/> - */ - -// THIS FILE IS GENERATED, DO NOT EDIT - -package tech.libeufin.nexus - -enum class ExternalBankTransactionDomainCode(val description: String) { - ACMT("Account Management"), - CAMT("Cash Management"), - CMDT("Commodities"), - DERV("Derivatives"), - FORX("Foreign Exchange"), - LDAS("Loans, Deposits & Syndications"), - PMET("Precious Metal"), - PMNT("Payments"), - SECU("Securities"), - TRAD("Trade Services"), - XTND("Extended Domain"), -} - -enum class ExternalBankTransactionFamilyCode(val description: String) { - ACCB("Account Balancing"), - ACOP("Additional Miscellaneous Credit Operations"), - ADOP("Additional Miscellaneous Debit Operations"), - BLOC("Blocked Transactions"), - CAPL("Cash Pooling"), - CASH("Miscellaneous Securities Operations"), - CCRD("Customer Card Transactions"), - CLNC("Clean Collection"), - CNTR("Counter Transactions"), - COLC("Custody Collection"), - COLL("Collateral Management"), - CORP("Corporate Action"), - CSLN("Consumer Loans"), - CUST("Custody"), - DCCT("Documentary Credit"), - DLVR("Delivery"), - DOCC("Documentary Collection"), - DRFT("Drafts"), - FTDP("Fixed Term Deposits"), - FTLN("Fixed Term Loans"), - FTUR("Futures"), - FWRD("Forwards"), - GUAR("Guarantees"), - ICCN("Issued Cash Concentration Transactions"), - ICDT("Issued Credit Transfers"), - ICHQ("Issued Cheques"), - IDDT("Issued Direct Debits"), - IRCT("Issued Real-Time Credit Transfers"), - LACK("Lack"), - LBOX("Lockbox Transactions"), - LFUT("Listed Derivatives - Futures"), - LOCT("Stand-By Letter Of Credit"), - LOPT("Listed Derivatives - Options"), - MCOP("Miscellaneous Credit Operations"), - MCRD("Merchant Card Transactions"), - MDOP("Miscellaneous Debit Operations"), - MGLN("Mortgage Loans"), - NDFX("Non Deliverable"), - NSET("Non Settled"), - NTAV("Not Available"), - NTDP("Notice Deposits"), - NTLN("Notice Loans"), - OBND("OTC Derivatives - Bonds"), - OCRD("OTC Derivatives - Credit"), - OEQT("OTC Derivatives - Equity"), - OIRT("OTC Derivatives - Interest Rates"), - OPCL("Opening & Closing"), - OPTN("Options"), - OSED("OTC Derivatives - Structured Exotic Derivatives"), - OSWP("OTC Derivatives – Swaps"), - OTHB("CSD Blocked transactions"), - OTHR("Other"), - RCCN("Received Cash Concentration Transactions"), - RCDT("Received Credit Transfers"), - RCHQ("Received Cheques"), - RDDT("Received Direct Debits"), - RRCT("Received Real-Time Credit Transfers"), - SETT("Trade, Clearing and Settlement"), - SPOT("Spots"), - SWAP("Swaps"), - SYDN("Syndications"), -} - -enum class ExternalBankTransactionSubFamilyCode(val description: String) { - ACCC("Account Closing"), - ACCO("Account Opening"), - ACCT("Account Transfer"), - ACDT("ACH Credit"), - ACOR("ACH Corporate Trade"), - ADBT("ACH Debit"), - ADJT("Adjustments (Generic)"), - APAC("ACH Pre-Authorised"), - ARET("ACH Return"), - AREV("ACH Reversal"), - ARPD("ARP Debit"), - ASET("ACH Settlement"), - ATXN("ACH Transaction"), - AUTT("Automatic Transfer"), - BBDD("SEPA B2B Direct Debit"), - BCDP("Branch Deposit"), - BCHQ("Bank Cheque"), - BCKV("Back Value"), - BCWD("Branch Withdrawl"), - BFWD("Bond Forward"), - BIDS("Repurchase Offer/Issuer Bid/Reverse Rights."), - BKFE("Bank Fees"), - BONU("Bonus Issue/Capitalisation Issue"), - BOOK("Internal Book Transfer"), - BPUT("Put Redemption"), - BROK("Brokerage Fee"), - BSBC("Sell Buy Back"), - BSBO("Buy Sell Back"), - CAJT("Credit Adjustments (Generic)"), - CAPG("Capital Gains Distribution"), - CASH("Cash Letter"), - CCCH("Certified Customer Cheque"), - CCHQ("Cheque"), - CCIR("Cross Currency IRS"), - CCPC("CCP Cleared Initial Margin"), - CCPM("CCP Cleared Variation Margin"), - CCSM("CCP Cleared Segregated Initial Margin"), - CDIS("Controlled Disbursement"), - CDPT("Cash Deposit"), - CHAR("Charge/Fees"), - CHKD("Check Deposit"), - CHRG("Charges (Generic)"), - CLAI("Compensation/Claims"), - CLCQ("Circular Cheque"), - CMBO("Corporate Mark Broker Owned"), - CMCO("Corporate Mark Client Owned"), - COME("Commission Excluding Taxes (Generic)"), - COMI("Commission Including Taxes (Generic)"), - COMM("Commission (Generic)"), - COMT("Non Taxable Commissions (Generic)"), - CONV("Conversion"), - COVE("Cover Transaction"), - CPEN("Cash Penalties"), - CPRB("Corporate Rebate"), - CQRV("Cheque Reversal"), - CRCQ("Crossed Cheque"), - CRDS("Credit DefaultSwap"), - CROS("Cross Trade"), - CRPR("Cross Product"), - CRSP("Credit Support"), - CRTL("Credit Line"), - CSHA("Cash Letter Adjustment"), - CSLI("Cash In Lieu"), - CWDL("Cash Withdrawal"), - DAJT("Debit Adjustments (Generic)"), - DDFT("Discounted Draft"), - DDWN("Drawdown"), - DECR("Decrease in Value"), - DMCG("Draft Maturity Change"), - DMCT("Domestic Credit Transfer"), - DPST("Deposit"), - DRAW("Drawing"), - DRIP("Dividend Reinvestment"), - DSBR("Controlled Disbursement"), - DTCH("Dutch Auction"), - DVCA("Cash Dividend"), - DVOP("Dividend Option"), - ENCT("Nordic Payment Council Credit Transfer"), - EQBO("Equity Mark Broker Owned"), - EQCO("Equity Mark Client Owned"), - EQPT("Equity Option"), - EQUS("Equity Swap"), - ERTA("Exchange Rate Adjustment"), - ERWA("Lending Income"), - ERWI("Borrowing Fee"), - ESCT("SEPA Credit Transfer"), - ESDD("SEPA Core Direct Debit"), - EXOF("Exchange"), - EXPT("Exotic Option"), - EXRI("Call On Intermediate Securities"), - EXTD("Exchange Traded Derivatives"), - EXWA("Warrant Exercise/Warrant Conversion"), - FCDP("Foreign Currencies Deposit"), - FCTA("Factor Update"), - FCWD("Foreign Currencies Withdrawal"), - FEES("Fees (Generic)"), - FICT("Financial Institution Credit Transfer"), - FIDD("Financial Institution Direct Debit Payment"), - FIOA("Financial Institution Own Account Transfer"), - FIXI("Fixed Income"), - FLTA("Float Adjustment"), - FRZF("Freeze Of Funds"), - FUCO("Futures Commission"), - FUTU("Future Variation Margin"), - FWBC("Forwards Broker Owned Collateral"), - FWCC("Forwards Client Owned Collateral"), - FWSB("MFA Segregated Broker Cash Collateral"), - FWSC("MFA Segregated Client Cash Collateral"), - GEN1("Withdrawal/Distribution"), - GEN2("Deposit/Contribution"), - IADD("Invoice Accepted with Differed Due Date"), - INFD("Fixed Deposit Interest Amount"), - INSP("Inspeci/Share Exchange"), - INTR("Interest Payment"), - ISSU("Depositary Receipt Issue"), - LBCA("Credit Adjustment"), - LBDP("Deposit"), - LIQU("Liquidation Dividend / Liquidation Payment"), - MARG("Margin Payments"), - MBSB("Mortgage Back Segregated Broker Cash Collateral"), - MBSC("Mortgage Back Segregated Client Cash Collateral"), - MCAL("Full Call / Early Redemption"), - MGCC("Margin Client Owned Cash Collateral"), - MGSC("Initial Futures Margin Segregated Client Cash Collateral"), - MIXD("Mixed Deposit"), - MNFE("Management Fees"), - MRGR("Merger"), - MSCD("Miscellaneous Deposit"), - NETT("Netting"), - NPCC("Non Presented Circular Cheques"), - NSYN("Non Syndicated"), - NTAV("Not Available"), - NWID("New issue distribution"), - OCCC("Client owned OCC pledged collateral"), - ODFT("Overdraft"), - ODLT("Odd Lot Sale/Purchase"), - OODD("One-Off Direct Debit"), - OPBC("Option Broker Owned Collateral"), - OPCC("Option Client Owned Collateral"), - OPCQ("Open Cheque"), - OPSB("OTC Option Segregated Broker Cash Collateral"), - OPSC("OTC Option Segregated Client Cash Collateral"), - OPTN("FX Option"), - ORCQ("Order Cheque"), - OTCC("OTC CCP"), - OTCD("OTC Derivatives"), - OTCG("OTC"), - OTCN("OTC Non-CCP"), - OTHR("Other"), - OVCH("Overdraft Charge"), - OWNE("External Account Transfer"), - OWNI("Internal Account Transfer"), - PADD("Pre-Authorised Direct Debit"), - PAIR("Pair-Off"), - PCAL("Partial Redemption With Reduction Of Nominal Value"), - PLAC("Placement"), - PMDD("Direct Debit"), - PORT("Portfolio Move"), - POSC("Credit Card Payment"), - POSD("Point-of-Sale (POS) Payment - Debit Card"), - PPAY("Principal Payment"), - PRCT("Priority Credit Transfer"), - PRDD("Reversal Due To Payment Reversal"), - PRED("Partial Redemption Without Reduction Of Nominal Value"), - PRII("Interest Payment with Principles"), - PRIN("Interest Payment with Principles"), - PRIO("Priority Issue"), - PRUD("Principal Pay-Down/Pay-Up"), - PSTE("Posting Error"), - RCDD("Reversal Due To Payment Cancellation Request"), - RCOV("Reversal due to a Cover Transaction Return"), - REAA("Redemption Asset Allocation"), - REDM("Final Maturity"), - REPU("Repo"), - RESI("Futures Residual Amount"), - RHTS("Rights Issue/Subscription Rights/Rights Offer"), - RIMB("Reimbursement (Generic)"), - RNEW("Renewal"), - RPBC("Bi-lateral repo broker owned collateral"), - RPCC("Repo client owned collateral"), - RPCR("Reversal Due To Payment Cancellation Request"), - RPMT("Repayment"), - RPSB("Bi-lateral Repo Segregated Broker Cash Collateral"), - RPSC("Bi-lateral Repo Segregated Client Cash Collateral"), - RRTN("Reversal Due To Payment Return"), - RVPO("Reverse Repo"), - RWPL("Redemption Withdrawing Plan"), - SABG("Settlement Against Bank Guarantee"), - SALA("Payroll/Salary Payment"), - SBSC("Securities Buy Sell Sell Buy Back"), - SCIE("Single Currency IRS Exotic"), - SCIR("Single Currency IRS"), - SCRP("Securities Cross Products"), - SDVA("Same Day Value Credit Transfer"), - SECB("Securities Borrowing"), - SECL("Securities Lending"), - SHBC("Broker owned collateral Short Sale"), - SHCC("Client owned collateral Short Sale"), - SHPR("Equity Premium Reserve"), - SHSL("Short Sell"), - SLBC("Lending Broker Owned Cash Collateral"), - SLCC("Lending Client Owned Cash Collateral"), - SLEB("Securities Lending And Borrowing"), - SLOA("SecuredLoan"), - SOSE("Settlement Of Sight Export Document"), - SOSI("Settlement Of Sight Import Document"), - SSPL("Subscription Savings Plan"), - STAC("Settlement After Collection"), - STAM("Settlement At Maturity"), - STDO("Standing Order"), - STLM("Settlement"), - STLR("Settlement Under Reserve"), - STOD("Bill of Exchange Settlement on Demand"), - SUAA("Subscription Asset Allocation"), - SUBS("Subscription"), - SWAP("Swap Payment"), - SWBC("Swap Broker Owned Collateral"), - SWCC("Client Owned Collateral"), - SWEP("Sweep"), - SWFP("Final Payment"), - SWIC("Switch"), - SWPP("Partial Payment"), - SWPT("Swaption"), - SWRS("Reset Payment"), - SWSB("ISDA/CSA Segregated Broker Cash Collateral"), - SWSC("ISDA/CSA Segregated Client Cash Collateral"), - SWUF("Upfront Payment"), - SYND("Syndicated"), - TAXE("Taxes (Generic)"), - TBAC("TBA Closing"), - TBAS("To Be Announced"), - TBBC("TBA Broker owned cash collateral"), - TBCC("TBA Client owned cash collateral"), - TCDP("Travellers Cheques Deposit"), - TCWD("Travellers Cheques Withdrawal"), - TEND("Tender"), - TOPG("Topping"), - TOUT("Transfer Out"), - TRAD("Trade"), - TRCP("Treasury Cross Product"), - TREC("Tax Reclaim"), - TRFE("Transaction Fees"), - TRIN("Transfer In"), - TRPO("Triparty Repo"), - TRVO("Triparty Reverse Repo"), - TTLS("Treasury Tax And Loan Service"), - TURN("Turnaround"), - UDFT("Dishonoured/Unpaid Draft"), - UNCO("Underwriting Commission"), - UPCQ("Unpaid Cheque"), - UPCT("Unpaid Card Transaction"), - UPDD("Reversal Due To Return/Unpaid Direct Debit"), - URCQ("Cheque Under Reserve"), - URDD("Direct Debit Under Reserve"), - VALD("Value Date"), - VCOM("Credit Transfer With Agreed Commercial Information"), - WITH("Withholding Tax"), - XBCP("Cross-Border Credit Card Payment"), - XBCQ("Foreign Cheque"), - XBCT("Cross-Border Credit Transfer"), - XBCW("Cross-Border Cash Withdrawal"), - XBRD("Cross-Border"), - XBSA("Cross-Border Payroll/Salary Payment"), - XBST("Cross-Border Standing Order"), - XCHC("Exchange Traded CCP"), - XCHG("Exchange Traded"), - XCHN("Exchange Traded Non-CCP"), - XICT("Cross-Border Intra Company Transfer"), - XPCQ("Unpaid Foreign Cheque"), - XRCQ("Foreign Cheque Under Reserve"), - XRTN("Cross Border Reversal Due to Payment Return"), - YTDA("YTD Adjustment"), - ZABA("Zero Balancing"), - ACON("ACH Concentration"), - BACT("Branch Account Transfer"), - COAT("Corporate Own Account Transfer"), - ICCT("Intra Company Transfer"), - LBDB("Debit"), - POSP("Point-of-Sale (POS) Payment"), - SMCD("Smart-Card Payment"), - SMRT("Smart-Card Payment"), - XBDD("Cross-Border Direct Debit"), -} - diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022Constants.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022Constants.kt @@ -1,35 +0,0 @@ -/* - * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. - - * LibEuFin is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation; either version 3, or - * (at your option) any later version. - - * LibEuFin is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General - * Public License for more details. - - * You should have received a copy of the GNU Affero General Public - * License along with LibEuFin; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/> - */ - -package tech.libeufin.nexus - -enum class HacAction(val description: String) { - FILE_UPLOAD("File submitted to the bank"), - FILE_DOWNLOAD("File downloaded from the bank"), - ES_UPLOAD("Electronic signature submitted to the bank"), - ES_DOWNLOAD("Electronic signature downloaded from the bank"), - ES_VERIFICATION("Signature verification"), - VEU_FORWARDING("Forwarding to EDS"), - VEU_VERIFICATION("EDS signature verification"), - VEU_VERIFICATION_END("VEU_VERIFICATION_END"), - VEU_CANCEL_ORDER("Cancellation of EDS order"), - ADDITIONAL("Additional information"), - ORDER_HAC_FINAL_POS("HAC end of order (positive)"), - ORDER_HAC_FINAL_NEG("HAC end of order (negative)") -} -\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022ExternalCodeSets.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022ExternalCodeSets.kt @@ -1,453 +0,0 @@ -/* - * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. - - * LibEuFin is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation; either version 3, or - * (at your option) any later version. - - * LibEuFin is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General - * Public License for more details. - - * You should have received a copy of the GNU Affero General Public - * License along with LibEuFin; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/> - */ - -// THIS FILE IS GENERATED, DO NOT EDIT - -package tech.libeufin.nexus - -enum class ExternalStatusReasonCode(val isoCode: String, val description: String) { - AB01("AbortedClearingTimeout", "Clearing process aborted due to timeout."), - AB02("AbortedClearingFatalError", "Clearing process aborted due to a fatal error."), - AB03("AbortedSettlementTimeout", "Settlement aborted due to timeout."), - AB04("AbortedSettlementFatalError", "Settlement process aborted due to a fatal error."), - AB05("TimeoutCreditorAgent", "Transaction stopped due to timeout at the Creditor Agent."), - AB06("TimeoutInstructedAgent", "Transaction stopped due to timeout at the Instructed Agent."), - AB07("OfflineAgent", "Agent of message is not online."), - AB08("OfflineCreditorAgent", "Creditor Agent is not online."), - AB09("ErrorCreditorAgent", "Transaction stopped due to error at the Creditor Agent."), - AB10("ErrorInstructedAgent", "Transaction stopped due to error at the Instructed Agent."), - AB11("TimeoutDebtorAgent", "Transaction stopped due to timeout at the Debtor Agent."), - AB12("InvalidConcurrentBatch", "Duplicate Concurrent Batch Sequence number– for Settlement Instructions."), - AB13("InvalidRoutingCodeUtilised", "Wrong Message Routing Type for Return-of-Funds."), - AB15("InvalidAccountNumberForSettlementType", "Instruction may not be placed on the Continuous Processing Line settlement processor."), - AB21("InvalidSettlementAgreementNumberSpecified", "Agreement number not valid (beneficiary)."), - AB26("InvalidBatchSettlementInstruction", "Settlement Instruction does not exist."), - AC01("IncorrectAccountNumber", "Account number is invalid or missing."), - AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing"), - AC03("InvalidCreditorAccountNumber", "Creditor account number invalid or missing"), - AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books."), - AC05("ClosedDebtorAccountNumber", "Debtor account number closed"), - AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), - AC07("ClosedCreditorAccountNumber", "Creditor account number closed"), - AC08("InvalidBranchCode", "Branch code is invalid or missing"), - AC09("InvalidAccountCurrency", "Account currency is invalid or missing"), - AC10("InvalidDebtorAccountCurrency", "Debtor account currency is invalid or missing"), - AC11("InvalidCreditorAccountCurrency", "Creditor account currency is invalid or missing"), - AC12("InvalidAccountType", "Account type missing or invalid."), - AC13("InvalidDebtorAccountType", "Debtor account type missing or invalid"), - AC14("InvalidCreditorAccountType", "Creditor account type missing or invalid"), - AC15("AccountDetailsChanged", "The account details for the counterparty have changed."), - AC16("CardNumberInvalid", "Credit or debit card number is invalid."), - AEXR("AlreadyExpiredRTP", "Request-to-pay Expiry Date and Time has already passed."), - AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), - AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), - AG03("TransactionNotSupported", "Transaction type not supported/authorized on this account"), - AG04("InvalidAgentCountry", "Agent country code is missing or invalid."), - AG05("InvalidDebtorAgentCountry", "Debtor agent country code is missing or invalid"), - AG06("InvalidCreditorAgentCountry", "Creditor agent country code is missing or invalid"), - AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), - AG08("InvalidAccessRights", "Transaction failed due to invalid or missing user or access right"), - AG09("PaymentNotReceived", "Original payment never received."), - AG10("AgentSuspended", "Agent of message is suspended from the Real Time Payment system."), - AG11("CreditorAgentSuspended", "Creditor Agent of message is suspended from the Real Time Payment system."), - AG12("NotAllowedBookTransfer", "Payment orders made by transferring funds from one account to another at the same financial institution (bank or payment institution) are not allowed."), - AG13("ForbiddenReturnPayment", "Returned payments derived from previously returned transactions are not allowed."), - AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect"), - ALAC("AlreadyAcceptedRTP", "Request-to-pay has already been accepted by the Debtor."), - AM01("ZeroAmount", "Specified message amount is equal to zero"), - AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), - AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), - AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), - AM05("Duplication", "Duplication"), - AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), - AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), - AM09("WrongAmount", "Amount received is not the amount agreed or expected"), - AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), - AM11("InvalidTransactionCurrency", "Transaction currency is invalid or missing"), - AM12("InvalidAmount", "Amount is invalid or missing"), - AM13("AmountExceedsClearingSystemLimit", "Transaction amount exceeds limits set by clearing system"), - AM14("AmountExceedsAgreedLimit", "Transaction amount exceeds limits agreed between bank and client"), - AM15("AmountBelowClearingSystemMinimum", "Transaction amount below minimum set by clearing system"), - AM16("InvalidGroupControlSum", "Control Sum at the Group level is invalid"), - AM17("InvalidPaymentInfoControlSum", "Control Sum at the Payment Information level is invalid"), - AM18("InvalidNumberOfTransactions", "Number of transactions is invalid or missing."), - AM19("InvalidGroupNumberOfTransactions", "Number of transactions at the Group level is invalid or missing"), - AM20("InvalidPaymentInfoNumberOfTransactions", "Number of transactions at the Payment Information level is invalid"), - AM21("LimitExceeded", "Transaction amount exceeds limits agreed between bank and client."), - AM22("ZeroAmountNotApplied", "Unable to apply zero amount to designated account. For example, where the rules of a service allow the use of zero amount payments, however the back-office system is unable to apply the funds to the account. If the rules of a service prohibit the use of zero amount payments, then code AM01 is used to report the error condition."), - AM23("AmountExceedsSettlementLimit", "Transaction amount exceeds settlement limit."), - APAR("AlreadyPaidRTP", "Request To Pay has already been paid by the Debtor."), - ARFR("AlreadyRefusedRTP", "Request-to-pay has already been refused by the Debtor."), - ARJR("AlreadyRejectedRTP", "Request-to-pay has already been rejected."), - ATNS("AttachementsNotSupported", "Attachments to the request-to-pay are not supported."), - BDAY("NotBusinessDay", "Settlement Cycle Day and Calendar day should be the same."), - BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number. (formerly CreditorConsistency)."), - BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), - BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), - BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), - BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), - BE08("MissingDebtorName", "Debtor name is missing"), - BE09("InvalidCountry", "Country code is missing or Invalid."), - BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid"), - BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid"), - BE12("InvalidCountryOfResidence", "Country code of residence is missing or Invalid."), - BE13("InvalidDebtorCountryOfResidence", "Country code of debtor's residence is missing or Invalid"), - BE14("InvalidCreditorCountryOfResidence", "Country code of creditor's residence is missing or Invalid"), - BE15("InvalidIdentificationCode", "Identification code missing or invalid."), - BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid"), - BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid"), - BE18("InvalidContactDetails", "Contact details missing or invalid"), - BE19("InvalidChargeBearerCode", "Charge bearer code for transaction type is invalid"), - BE20("InvalidNameLength", "Name length exceeds local rules for payment type."), - BE21("MissingName", "Name missing or invalid. Generic usage if cannot specifically identify debtor or creditor."), - BE22("MissingCreditorName", "Creditor name is missing"), - BE23("AccountProxyInvalid", "Phone number or email address, or any other proxy, used as the account proxy is unknown or invalid."), - CERI("CheckERI", "Credit transfer is not tagged as an Extended Remittance Information (ERI) transaction but contains ERI."), - CH03("RequestedExecutionDateOrRequestedCollectionDateTooFarInFuture", "Value in Requested Execution Date or Requested Collection Date is too far in the future"), - CH04("RequestedExecutionDateOrRequestedCollectionDateTooFarInPast", "Value in Requested Execution Date or Requested Collection Date is too far in the past"), - CH07("ElementIsNotToBeUsedAtB-andC-Level", "Element is not to be used at B- and C-Level"), - CH09("MandateChangesNotAllowed", "Mandate changes are not allowed"), - CH10("InformationOnMandateChangesMissing", "Information on mandate changes are missing"), - CH11("CreditorIdentifierIncorrect", "Value in Creditor Identifier is incorrect"), - CH12("CreditorIdentifierNotUnambiguouslyAtTransaction-Level", "Creditor Identifier is ambiguous at Transaction Level"), - CH13("OriginalDebtorAccountIsNotToBeUsed", "Original Debtor Account is not to be used"), - CH14("OriginalDebtorAgentIsNotToBeUsed", "Original Debtor Agent is not to be used"), - CH15("ElementContentIncludesMoreThan140Characters", "Content Remittance Information/Structured includes more than 140 characters"), - CH16("ElementContentFormallyIncorrect", "Content is incorrect"), - CH17("ElementNotAdmitted", "Element is not allowed"), - CH19("ValuesWillBeSetToNextTARGETday", "Values in Interbank Settlement Date or Requested Collection Date will be set to the next TARGET day"), - CH20("DecimalPointsNotCompatibleWithCurrency", "Number of decimal points not compatible with the currency"), - CH21("RequiredCompulsoryElementMissing", "Mandatory element is missing"), - CH22("COREandB2BwithinOnemessage", "SDD CORE and B2B not permitted within one message"), - CHQC("ChequeSettledOnCreditorAccount", "Cheque has been presented in cheque clearing and settled on the creditor’s account."), - CN01("AuthorisationCancelled", "Authorisation is cancelled."), - CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), - CURR("IncorrectCurrency", "Currency of the payment is incorrect"), - CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), - DC02("SettlementNotReceived", "Rejection of a payment due to covering FI settlement not being received."), - DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), - DS01("ElectronicSignaturesCorrect", "The electronic signature(s) is/are correct"), - DS02("OrderCancelled", "An authorized user has cancelled the order"), - DS03("OrderNotCancelled", "The user’s attempt to cancel the order was not successful"), - DS04("OrderRejected", "The order was rejected by the bank side (for reasons concerning content)"), - DS05("OrderForwardedForPostprocessing", "The order was correct and could be forwarded for postprocessing"), - DS06("TransferOrder", "The order was transferred to VEU"), - DS07("ProcessingOK", "All actions concerning the order could be done by the EBICS bank server"), - DS08("DecompressionError", "The decompression of the file was not successful"), - DS09("DecryptionError", "The decryption of the file was not successful"), - DS0A("DataSignRequested", "Data signature is required."), - DS0B("UnknownDataSignFormat", "Data signature for the format is not available or invalid."), - DS0C("SignerCertificateRevoked", "The signer certificate is revoked."), - DS0D("SignerCertificateNotValid", "The signer certificate is not valid (revoked or not active)."), - DS0E("IncorrectSignerCertificate", "The signer certificate is not present."), - DS0F("SignerCertificationAuthoritySignerNotValid", "The authority of the signer certification sending the certificate is unknown."), - DS0G("NotAllowedPayment", "Signer is not allowed to sign this operation type."), - DS0H("NotAllowedAccount", "Signer is not allowed to sign for this account."), - DS0K("NotAllowedNumberOfTransaction", "The number of transaction is over the number allowed for this signer."), - DS10("Signer1CertificateRevoked", "The certificate is revoked for the first signer."), - DS11("Signer1CertificateNotValid", "The certificate is not valid (revoked or not active) for the first signer."), - DS12("IncorrectSigner1Certificate", "The certificate is not present for the first signer."), - DS13("SignerCertificationAuthoritySigner1NotValid", "The authority of signer certification sending the certificate is unknown for the first signer."), - DS14("UserDoesNotExist", "The user is unknown on the server"), - DS15("IdenticalSignatureFound", "The same signature has already been sent to the bank"), - DS16("PublicKeyVersionIncorrect", "The public key version is not correct. This code is returned when a customer sends signature files to the financial institution after conversion from an older program version (old ES format) to a new program version (new ES format) without having carried out re-initialisation with regard to a public key change."), - DS17("DifferentOrderDataInSignatures", "Order data and signatures don’t match"), - DS18("RepeatOrder", "File cannot be tested, the complete order has to be repeated. This code is returned in the event of a malfunction during the signature check, e.g. not enough storage space."), - DS19("ElectronicSignatureRightsInsufficient", "The user’s rights (concerning his signature) are insufficient to execute the order"), - DS20("Signer2CertificateRevoked", "The certificate is revoked for the second signer."), - DS21("Signer2CertificateNotValid", "The certificate is not valid (revoked or not active) for the second signer."), - DS22("IncorrectSigner2Certificate", "The certificate is not present for the second signer."), - DS23("SignerCertificationAuthoritySigner2NotValid", "The authority of signer certification sending the certificate is unknown for the second signer."), - DS24("WaitingTimeExpired", "Waiting time expired due to incomplete order"), - DS25("OrderFileDeleted", "The order file was deleted by the bank server"), - DS26("UserSignedMultipleTimes", "The same user has signed multiple times"), - DS27("UserNotYetActivated", "The user is not yet activated (technically)"), - DS28("ReturnForTechnicalReason", "Message routed to the wrong environment."), - DT01("InvalidDate", "Invalid date (eg, wrong or missing settlement date)"), - DT02("InvalidCreationDate", "Invalid creation date and time in Group Header (eg, historic date)"), - DT03("InvalidNonProcessingDate", "Invalid non bank processing date (eg, weekend or local public holiday)"), - DT04("FutureDateNotSupported", "Future date not supported"), - DT05("InvalidCutOffDate", "Associated message, payment information block or transaction was received after agreed processing cut-off date, i.e., date in the past."), - DT06("ExecutionDateChanged", "Execution Date has been modified in order for transaction to be processed"), - DU01("DuplicateMessageID", "Message Identification is not unique."), - DU02("DuplicatePaymentInformationID", "Payment Information Block is not unique."), - DU03("DuplicateTransaction", "Transaction is not unique."), - DU04("DuplicateEndToEndID", "End To End ID is not unique."), - DU05("DuplicateInstructionID", "Instruction ID is not unique."), - DUPL("DuplicatePayment", "Payment is a duplicate of another payment"), - ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), - ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), - ED05("SettlementFailed", "Settlement of the transaction has failed."), - ED06("SettlementSystemNotAvailable", "Interbank settlement system not available."), - EDTL("ExpiryDateTooLong", "Expiry date time of the request-to-pay is too far in the future."), - EDTR("ExpiryDateTimeReached", "Expiry date time of the request-to-pay is already reached."), - ERIN("ERIOptionNotSupported", "Extended Remittance Information (ERI) option is not supported."), - FF01("InvalidFileFormat", "File Format incomplete or invalid"), - FF02("SyntaxError", "Syntax error reason is provided as narrative information in the additional reason information."), - FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), - FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid"), - FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), - FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid"), - FF07("InvalidPurpose", "Purpose is missing or invalid"), - FF08("InvalidEndToEndId", "End to End Id missing or invalid"), - FF09("InvalidChequeNumber", "Cheque number missing or invalid"), - FF10("BankSystemProcessingError", "File or transaction cannot be processed due to technical issues at the bank side"), - FF11("ClearingRequestAborted", "Clearing request rejected due it being subject to an abort operation."), - FF12("OriginalTransactionNotEligibleForRequestedReturn", "Original payment is not eligible to be returned given its current status."), - FF13("RequestForCancellationNotFound", "No record of request for cancellation found."), - FOCR("FollowingCancellationRequest", "Return following a cancellation request."), - FR01("Fraud", "Returned as a result of fraud."), - FRAD("FraudulentOrigin", "Cancellation requested following a transaction that was originated fraudulently. The use of the FraudulentOrigin code should be governed by jurisdictions."), - G000("PaymentTransferredAndTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is tracked. No further updates will follow from the Status Originator."), - G001("PaymentTransferredAndNotTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is not tracked. No further updates will follow from the Status Originator."), - G002("CreditDebitNotConfirmed", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account may not be confirmed same day. Update will follow from the Status Originator."), - G003("CreditPendingDocuments", "In a FIToFI Customer Credit Transfer: Credit to creditor’s account is pending receipt of required documents. The Status Originator has requested creditor to provide additional documentation. Update will follow from the Status Originator."), - G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), - G005("DeliveredWithServiceLevel", "Payment has been delivered to creditor agent with service level."), - G006("DeliveredWIthoutServiceLevel", "Payment has been delivered to creditor agent without service level."), - ID01("CorrespondingOriginalFileStillNotSent", "Signature file was sent to the bank but the corresponding original file has not been sent yet."), - IEDT("IncorrectExpiryDateTime", "Expiry date time of the request-to-pay is incorrect."), - INDT("InvalidDetails", "Details not valid for this field."), - IRNR("InitialRTPNeverReceived", "No initial request-to-pay has been received."), - ISWS("InvalidSettlementWindow", "Cannot schedule instruction for Night Window."), - MD01("NoMandate", "No Mandate"), - MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), - MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit"), - MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), - MD07("EndCustomerDeceased", "End customer is deceased."), - MINF("MissingInformation", "Information missing for the field or cannot be empty."), - MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), - MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), - NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), - NERI("NoERI", "Credit transfer is tagged as an Extended Remittance Information (ERI) transaction but does not contain ERI."), - NOAR("NonAgreedRTP", "No existing agreement for receiving request-to-pay messages."), - NOAS("NoAnswerFromCustomer", "No response from Beneficiary."), - NOCM("NotCompliantGeneric", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), - NOFR("OutstandingFundingForSettlement", "Continuous Processing Line on Hold Instruction."), - NOPG("NoPaymentGuarantee", "Requested payment guarantee (by Creditor) related to a request-to-pay cannot be provided."), - NRCH("PayerOrPayerRTPSPNotReachable", "Recipient side of the request-to-pay (payer or its request-to-pay service provider) is not reachable."), - PINS("TypeOfPaymentInstrumentNotSupported", "Type of payment requested in the request-to-pay is not supported by the payer."), - RC01("BankIdentifierIncorrect", "Bank identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), - RC02("InvalidBankIdentifier", "Bank identifier is invalid or missing."), - RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing"), - RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing"), - RC05("InvalidBICIdentifier", "BIC identifier is invalid or missing."), - RC06("InvalidDebtorBICIdentifier", "Debtor BIC identifier is invalid or missing"), - RC07("InvalidCreditorBICIdentifier", "Creditor BIC identifier is invalid or missing"), - RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), - RC09("InvalidDebtorClearingSystemMemberIdentifier", "Debtor ClearingSystemMember identifier is invalid or missing"), - RC10("InvalidCreditorClearingSystemMemberIdentifier", "Creditor ClearingSystemMember identifier is invalid or missing"), - RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing"), - RC12("MissingCreditorSchemeId", "Creditor Scheme Id is invalid or missing"), - RC13("ParticipantNotAnActiveMemberofRTGS", "Originator not active any more."), - RC15("ParticipantNotActiveMemberSettlementType", "Settlement agreement required."), - RC16("ParticipantNotActiveMemberofSADCRTGS", "Participant blocked from SADC-RTGS."), - RCON("RMessageConflict", "Conflict with R-Message"), - RECI("ReceiverCustomerInformation", "Further information regarding the intended recipient."), - REPR("RTPReceivedCanBeProcessed", "Request-to-pay has been received and can be processed further."), - RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), - RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), - RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), - RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), - RR04("RegulatoryReason", "Regulatory Reason"), - RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), - RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), - RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), - RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), - RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), - RR10("InvalidCharacterSet", "Character set supplied not valid for the country and payment type."), - RR11("InvalidDebtorAgentServiceID", "Invalid or missing identification of a bank proprietary service."), - RR12("InvalidPartyID", "Invalid or missing identification required within a particular country or payment type."), - RTNS("RTPNotSupportedForDebtor", "Debtor does not support request-to-pay transactions."), - RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), - S000("ValidRequestForCancellationAcknowledged", "Request for Cancellation is acknowledged following validation."), - S001("UETRFlaggedForCancellation", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been identified as being associated with a Request for Cancellation."), - S002("NetworkStopOfUETR", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been prevent from traveling across a messaging network."), - S003("RequestForCancellationForwarded", "Request for Cancellation has been forwarded to the payment processing/last payment processing agent."), - S004("RequestForCancellationDeliveryAcknowledgement", "Request for Cancellation has been acknowledged as delivered to payment processing/last payment processing agent."), - SBRN("SettlementBatchRemovalNotification", "Remove Concurrent Batch Processing Line on hold instruction."), - SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent."), - SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent."), - SL03("ServiceofClearingSystem", "Due to a specific service offered by the clearing system."), - SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), - SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), - SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), - SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), - SPII("RTPServiceProviderIdentifierIncorrect", "Identifier of the request-to-pay service provider is incorrect."), - TA01("TransmissonAborted", "The transmission of the file was not successful – it had to be aborted (for technical reasons)"), - TD01("NoDataAvailable", "There is no data available (for download)"), - TD02("FileNonReadable", "The file cannot be read (e.g. unknown format)"), - TD03("IncorrectFileStructure", "The file format is incomplete or invalid"), - TK01("TokenInvalid", "Token is invalid."), - TK02("SenderTokenNotFound", "Token used for the sender does not exist."), - TK03("ReceiverTokenNotFound", "Token used for the receiver does not exist."), - TK09("TokenMissing", "Token required for request is missing."), - TKCM("TokenCounterpartyMismatch", "Token found with counterparty mismatch."), - TKSG("TokenSingleUse", "Single Use Token already used."), - TKSP("TokenSuspended", "Token found with suspended status."), - TKVE("TokenValueLimitExceeded", "Token found with value limit rule violation."), - TKXP("TokenExpired", "Token expired."), - TM01("InvalidCutOffTime", "Associated message, payment information block, or transaction was received after agreed processing cut-off time."), - TS01("TransmissionSuccessful", "The (technical) transmission of the file was successful."), - TS04("TransferToSignByHand", "The order was transferred to pass by accompanying note signed by hand"), - UCRD("UnknownCreditor", "Unknown Creditor."), - UPAY("UnduePayment", "Payment is not justified."), -} - -enum class ExternalPaymentGroupStatusCode(val isoCode: String, val description: String) { - ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), - ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), - ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement on the debtor's account has been completed."), - ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment initiation has been accepted for execution."), - ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), - ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), - PART("PartiallyAccepted", "A number of transactions have been accepted, whereas another number of transactions have not yet achieved"), - PDNG("Pending", "Payment initiation or individual transaction included in the payment initiation is pending. Further checks and status update will be performed."), - RCVD("Received", "Payment initiation has been received by the receiving agent"), - RJCT("Rejected", "Payment initiation or individual transaction included in the payment initiation has been rejected."), -} - -enum class ExternalPaymentTransactionStatusCode(val isoCode: String, val description: String) { - ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), - ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), - ACFC("AcceptedFundsChecked", "Preceding check of technical validation and customer profile was successful and an automatic funds check was positive."), - ACIS("AcceptedandChequeIssued", "Payment instruction to issue a cheque has been accepted, and the cheque has been issued but not yet been deposited or cleared."), - ACPD("AcceptedClearingProcessed", "Status of transaction released from the Debtor Agent and accepted by the clearing."), - ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement completed."), - ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment instruction has been accepted for execution."), - ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), - ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), - ACWP("AcceptedWithoutPosting", "Payment instruction included in the credit transfer is accepted without being posted to the creditor customer’s account."), - BLCK("Blocked", "Payment transaction previously reported with status 'ACWP' is blocked, for example, funds will neither be posted to the Creditor's account, nor be returned to the Debtor."), - CANC("Cancelled", "Payment initiation has been successfully cancelled after having received a request for cancellation."), - CPUC("CashPickedUpByCreditor", "Cash has been picked up by the Creditor."), - PATC("PartiallyAcceptedTechnicalCorrect", "Payment initiation needs multiple authentications, where some but not yet all have been performed. Syntactical and semantical validations are successful."), - PDNG("Pending", "Payment instruction is pending. Further checks and status update will be performed."), - PRES("Presented", "Request for Payment has been presented to the Debtor."), - RCVD("Received", "Payment instruction has been received."), - RJCT("Rejected", "Payment instruction has been rejected."), -} - -enum class ExternalReturnReasonCode(val isoCode: String, val description: String) { - AC01("IncorrectAccountNumber", "Format of the account number specified is not correct"), - AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing."), - AC03("InvalidCreditorAccountNumber", "Wrong IBAN in SCT"), - AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books"), - AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), - AC07("ClosedCreditorAccountNumber", "Creditor account number closed."), - AC13("InvalidDebtorAccountType", "Debtor account type is missing or invalid"), - AC14("InvalidAgent", "An agent in the payment chain is invalid."), - AC15("AccountDetailsChanged", "Account details have changed."), - AC16("AccountInSequestration", "Account is in sequestration."), - AC17("AccountInLiquidation", "Account is in liquidation."), - AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), - AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), - AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), - AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect."), - AM01("ZeroAmount", "Specified message amount is equal to zero"), - AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), - AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), - AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), - AM05("Duplication", "Duplication"), - AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), - AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), - AM09("WrongAmount", "Amount received is not the amount agreed or expected"), - AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), - ARDT("AlreadyReturnedTransaction", "Already returned original SCT"), - BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number, organisation ID or private ID."), - BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), - BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), - BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), - BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), - BE08("BankError", "Returned as a result of a bank error."), - BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid."), - BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid."), - BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid."), - BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid."), - CN01("AuthorisationCancelled", "Authorisation is cancelled."), - CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), - CNPC("CashNotPickedUp", "Cash not picked up by Creditor or cash could not be delivered to Creditor"), - CURR("IncorrectCurrency", "Currency of the payment is incorrect"), - CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), - DC04("NoCustomerCreditTransferReceived", "Return of Covering Settlement due to the underlying Credit Transfer details not being received."), - DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), - DS28("ReturnForTechnicalReason", "Return following technical problems resulting in erroneous transaction."), - DT01("InvalidDate", "Invalid date (eg, wrong settlement date)"), - DT02("ChequeExpired", "Cheque has been issued but not deposited and is considered expired."), - DT04("FutureDateNotSupported", "Future date not supported."), - DUPL("DuplicatePayment", "Payment is a duplicate of another payment."), - ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), - ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), - ED05("SettlementFailed", "Settlement of the transaction has failed."), - EMVL("EMVLiabilityShift", "The card payment is fraudulent and was not processed with EMV technology for an EMV card."), - ERIN("ERIOptionNotSupported", "The Extended Remittance Information (ERI) option is not supported."), - FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), - FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid."), - FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), - FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid."), - FF07("InvalidPurpose", "Purpose is missing or invalid."), - FOCR("FollowingCancellationRequest", "Return following a cancellation request"), - FR01("Fraud", "Returned as a result of fraud."), - FRTR("FinalResponseMandateCancelled", "Final response/tracking is recalled as mandate is cancelled."), - G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), - MD01("NoMandate", "No Mandate"), - MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), - MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit."), - MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), - MD07("EndCustomerDeceased", "End customer is deceased."), - MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), - MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), - NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), - NOAS("NoAnswerFromCustomer", "No response from Beneficiary"), - NOCM("NotCompliant", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), - NOOR("NoOriginalTransactionReceived", "Original SCT never received"), - PINL("PINLiabilityShift", "The card payment is fraudulent (lost and stolen fraud) and was processed as EMV transaction without PIN verification."), - RC01("BankIdentifierIncorrect", "Bank Identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), - RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing."), - RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing."), - RC07("InvalidCreditorBICIdentifier", "Incorrrect BIC of the beneficiary Bank in the SCTR"), - RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), - RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing."), - RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), - RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), - RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), - RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), - RR04("RegulatoryReason", "Regulatory Reason"), - RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), - RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), - RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), - RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), - RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), - RR11("InvalidDebtorAgentServiceIdentification", "Invalid or missing identification of a bank proprietary service."), - RR12("InvalidPartyIdentification", "Invalid or missing identification required within a particular country or payment type."), - RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), - SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent"), - SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent"), - SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), - SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), - SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), - SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), - SP01("PaymentStopped", "Payment is stopped by account holder."), - SP02("PreviouslyStopped", "Previously stopped by means of a stop payment advise."), - SVNR("ServiceNotRendered", "The card payment is returned since a cash amount rendered was not correct or goods or a service was not rendered to the customer, e.g. in an e-commerce situation."), - TM01("CutOffTime", "Associated message was received after agreed processing cut-off time."), - TRAC("RemovedFromTracking", "Return following direct debit being removed from tracking process."), - UPAY("UnduePayment", "Payment is not justified."), -} - diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt @@ -33,6 +33,7 @@ import tech.libeufin.nexus.api.revenueApi import tech.libeufin.nexus.api.wireGatewayApi import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.nexus.db.Database +import com.github.ajalt.clikt.core.main internal val logger: Logger = LoggerFactory.getLogger("libeufin-nexus") diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/XmlCombinators.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/XmlCombinators.kt @@ -156,35 +156,49 @@ class XmlDestructor internal constructor(private val el: Element) { if (!children.hasNext()) { throw DestructionError("expected unique '${el.tagName}.$tag', got none") } - val el = children.next() + val child = children.next() if (children.hasNext()) { throw DestructionError("expected unique '${el.tagName}.$tag', got ${children.asSequence().count() + 1}") } - return XmlDestructor(el) + return XmlDestructor(child) } fun opt(tag: String): XmlDestructor? { val children = el.childrenByTag(tag).iterator() if (!children.hasNext()) { return null } - val el = children.next() + val child = children.next() if (children.hasNext()) { throw DestructionError("expected optional '${el.tagName}.$tag', got ${children.asSequence().count() + 1}") } - return XmlDestructor(el) + return XmlDestructor(child) } fun <T> one(path: String, f: XmlDestructor.() -> T): T = f(one(path)) fun <T> opt(path: String, f: XmlDestructor.() -> T): T? = opt(path)?.run(f) fun text(): String = el.textContent - fun textProvided(): String? = if (el.textContent != "NOTPROVIDED") el.textContent else null fun bool(): Boolean = el.textContent.toBoolean() fun date(): LocalDate = LocalDate.parse(text(), DateTimeFormatter.ISO_DATE) fun dateTime(): LocalDateTime = LocalDateTime.parse(text(), DateTimeFormatter.ISO_DATE_TIME) - inline fun <reified T : kotlin.Enum<T>> enum(): T = java.lang.Enum.valueOf(T::class.java, text()) + inline fun <reified T : Enum<T>> enum(): T = java.lang.Enum.valueOf(T::class.java, text()) + + fun optAttr(index: String): String? { + val attr = el.getAttribute(index) + if (attr == "") { + return null + } else { + return attr + } + } + fun attr(index: String): String { + val attr = optAttr(index) + if (attr == null) { + throw DestructionError("missing attribute '$index' at '${el.tagName}'") + } + return attr + } - fun attr(index: String): String = el.getAttribute(index) companion object { fun <T> fromStream(xml: InputStream, root: String, f: XmlDestructor.() -> T): T { diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt @@ -26,13 +26,14 @@ import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.util.pipeline.* import tech.libeufin.common.* -import tech.libeufin.nexus.IncomingPayment import tech.libeufin.nexus.NexusConfig import tech.libeufin.nexus.checkCurrency import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.db.ExchangeDAO import tech.libeufin.nexus.db.ExchangeDAO.TransferResult import tech.libeufin.nexus.db.PaymentDAO.IncomingRegistrationResult +import tech.libeufin.nexus.ebics.randEbicsId +import tech.libeufin.nexus.iso20022.* import java.time.Instant @@ -46,13 +47,10 @@ fun Routing.wireGatewayApi(db: Database, cfg: NexusConfig) = authApi(cfg.wireGat val req = call.receive<TransferRequest>() cfg.checkCurrency(req.amount) req.credit_account.expectRequestIban() - val bankId = run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } + val endToEndId = randEbicsId() val res = db.exchange.transfer( req, - bankId, + endToEndId, Instant.now() ) when (res) { @@ -111,16 +109,13 @@ fun Routing.wireGatewayApi(db: Database, cfg: NexusConfig) = authApi(cfg.wireGat metadata: TalerIncomingMetadata ) { cfg.checkCurrency(amount) - debitAccount.expectRequestIban() + val debitAccount = debitAccount.expectRequestIban() val timestamp = Instant.now() - val bankId = run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } + val bankId = randEbicsId() val res = db.payment.registerTalerableIncoming(IncomingPayment( amount = amount, - debitPaytoUri = debitAccount.toString(), - wireTransferSubject = subject, + debtorPayto = debitAccount, + subject = subject, executionTime = timestamp, bankId = bankId ), metadata) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/DbInit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/DbInit.kt @@ -19,6 +19,7 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option @@ -29,7 +30,9 @@ import tech.libeufin.common.db.pgDataSource import tech.libeufin.nexus.dbConfig import tech.libeufin.nexus.logger -class DbInit : CliktCommand("Initialize the libeufin-nexus database", name = "dbinit") { +class DbInit : CliktCommand("dbinit") { + override fun help(context: Context) = "Initialize the libeufin-nexus database" + private val common by CommonOption() private val reset by option( "--reset", "-r", diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsFetch.kt @@ -20,6 +20,8 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context +import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.arguments.unique @@ -29,21 +31,20 @@ import com.github.ajalt.clikt.parameters.types.enum import kotlinx.coroutines.* import tech.libeufin.common.* import tech.libeufin.nexus.* -import tech.libeufin.nexus.db.Database -import tech.libeufin.nexus.db.PaymentDAO.IncomingRegistrationResult +import tech.libeufin.nexus.db.* +import tech.libeufin.nexus.db.PaymentDAO.* import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* import java.io.IOException import java.io.InputStream -import java.time.Duration import java.time.Instant -import kotlin.time.toKotlinDuration -/** Ingests an outgoing [payment] into [db] */ -suspend fun ingestOutgoingPayment( +/** Register an outgoing [payment] into [db] */ +suspend fun registerOutgoingPayment( db: Database, payment: OutgoingPayment -) { - val metadata: Pair<ShortHashCode, ExchangeUrl>? = payment.wireTransferSubject?.let { +): OutgoingRegistrationResult { + val metadata: Pair<ShortHashCode, ExchangeUrl>? = payment.subject?.let { runCatching { parseOutgoingTxMetadata(it) }.getOrNull() } val result = db.payment.registerOutgoing(payment, metadata?.first, metadata?.second) @@ -55,13 +56,25 @@ suspend fun ingestOutgoingPayment( } else { logger.debug("{} already seen", payment) } + return result +} + +/** Register an outgoing [payment] into [db] */ +suspend fun registerOutgoingBatch( + db: Database, + batch: OutgoingBatch +) { + logger.info("BATCH ${batch.executionTime.fmtDate()} ${batch.msgId}") + for (it in db.initiated.unsettledTxInBatch(batch.msgId, batch.executionTime)) { + registerOutgoingPayment(db, it) + } } /** - * Ingest an incoming [payment] into [db] + * Register an incoming [payment] into [db] * Stores the payment into valid talerable ones or bounces it */ -suspend fun ingestIncomingPayment( +suspend fun registerIncomingPayment( db: Database, cfg: NexusIngestConfig, payment: IncomingPayment, @@ -69,7 +82,7 @@ suspend fun ingestIncomingPayment( suspend fun bounce(msg: String) { if (payment.bankId == null) { logger.debug("{} ignored: missing bank ID", payment) - return; + return } when (cfg.accountType) { AccountType.exchange -> { @@ -84,6 +97,7 @@ suspend fun ingestIncomingPayment( val result = db.payment.registerMalformedIncoming( payment, payment.amount, + randEbicsId(), Instant.now() ) if (result.new) { @@ -103,7 +117,7 @@ suspend fun ingestIncomingPayment( } } } - runCatching { parseIncomingTxMetadata(payment.wireTransferSubject) }.fold( + runCatching { parseIncomingTxMetadata(payment.subject) }.fold( onSuccess = { metadata -> when (val res = db.payment.registerTalerableIncoming(payment, metadata)) { IncomingRegistrationResult.ReservePubReuse -> bounce("reverse pub reuse") @@ -120,8 +134,8 @@ suspend fun ingestIncomingPayment( ) } -/** Ingest a [tx] notification into [db] */ -suspend fun ingestTransaction( +/** Register a [tx] notification into [db] */ +suspend fun registerTransaction( db: Database, cfg: NexusIngestConfig, tx: TxNotification, @@ -130,74 +144,113 @@ suspend fun ingestTransaction( logger.debug("IGNORE {}", tx) } else { when (tx) { - is IncomingPayment -> ingestIncomingPayment(db, cfg, tx) - is OutgoingPayment -> ingestOutgoingPayment(db, tx) - is TxNotification.Reversal -> { - logger.error("BOUNCE '${tx.msgId}': ${tx.reason}") - db.initiated.reversal(tx.msgId, "Payment bounced: ${tx.reason}") + is IncomingPayment -> registerIncomingPayment(db, cfg, tx) + is OutgoingPayment -> registerOutgoingPayment(db, tx) + is OutgoingBatch -> registerOutgoingBatch(db, tx) + is OutgoingReversal -> { + logger.error("{}", tx) + db.initiated.txStatusUpdate(tx.endToEndId, tx.msgId, StatusUpdate.permanent_failure, "Payment bounced: ${tx.reason}") } } } } -/** Ingest an EBICS [payload] of [doc] into [db] */ -private suspend fun ingestPayload( +/** Register a single EBICS [xml] [document] into [db] */ +suspend fun registerFile( db: Database, cfg: NexusEbicsConfig, - payload: InputStream, + xml: InputStream, doc: OrderDoc ) { - /** Ingest a single EBICS [xml] [document] into [db] */ - suspend fun ingest(xml: InputStream) { - when (doc) { - OrderDoc.report, OrderDoc.statement, OrderDoc.notification -> { - try { - parseTx(xml, cfg.currency, cfg.dialect).forEach { tx -> - ingestTransaction(db, cfg.ingest, tx) - } - } catch (e: Exception) { - throw Exception("Ingesting notifications failed", e) + when (doc) { + OrderDoc.report, OrderDoc.statement, OrderDoc.notification -> { + try { + parseTx(xml, cfg.currency, cfg.dialect).forEach { tx -> + registerTransaction(db, cfg.ingest, tx) } + } catch (e: Exception) { + throw Exception("Ingesting notifications failed", e) } - OrderDoc.acknowledgement -> { - val acks = parseCustomerAck(xml) - for (ack in acks) { - when (ack.actionType) { - HacAction.ORDER_HAC_FINAL_POS -> { - logger.debug("{}", ack) - db.initiated.logSuccess(ack.orderId!!)?.let { requestUID -> - logger.info("Payment '$requestUID' accepted at ${ack.timestamp.fmtDateTime()}") - } + } + OrderDoc.acknowledgement -> { + val acks = parseCustomerAck(xml) + for (ack in acks) { + when (ack.actionType) { + HacAction.ORDER_HAC_FINAL_POS -> { + logger.debug("{}", ack) + db.initiated.orderSuccess(ack.orderId!!)?.let { messageId -> + logger.info("Batch $messageId order ${ack.orderId} accepted at ${ack.timestamp.fmtDateTime()}") } - HacAction.ORDER_HAC_FINAL_NEG -> { - logger.debug("{}", ack) - db.initiated.logFailure(ack.orderId!!)?.let { (requestUID, msg) -> - logger.error("Payment '$requestUID' refused at ${ack.timestamp.fmtDateTime()}${if (msg != null) ": $msg" else ""}") - } + } + HacAction.ORDER_HAC_FINAL_NEG -> { + logger.debug("{}", ack) + db.initiated.orderFailure(ack.orderId!!)?.let { (messageId, msg) -> + logger.error("Batch $messageId order ${ack.orderId} refused at ${ack.timestamp.fmtDateTime()}${if (msg != null) ": $msg" else ""}") } - else -> { - logger.debug("{}", ack) - if (ack.orderId != null) { - db.initiated.logMessage(ack.orderId, ack.msg()) - } + } + else -> { + logger.debug("{}", ack) + if (ack.orderId != null) { + db.initiated.orderStep(ack.orderId, ack.msg()) } } } } - OrderDoc.status -> { - val status = parseCustomerPaymentStatusReport(xml) - val msg = status.msg() - logger.debug("{}", status) - if (status.paymentCode == ExternalPaymentGroupStatusCode.RJCT) { - db.initiated.bankFailure(status.msgId, msg) - logger.error("Transaction '${status.msgId}' was rejected : $msg") - } else { - db.initiated.bankMessage(status.msgId, msg) + } + OrderDoc.status -> { + val msgStatus = parseCustomerPaymentStatusReport(xml) + logger.debug("{}", msgStatus) + if (msgStatus.code != null) { + val msg = msgStatus.msg() + val state = when (msgStatus.code) { + ExternalPaymentGroupStatusCode.ACSC -> StatusUpdate.success + ExternalPaymentGroupStatusCode.RJCT -> { + logger.error("Batch ${msgStatus.id} failed: $msg") + StatusUpdate.permanent_failure + } + else -> StatusUpdate.pending + } + db.initiated.batchStatusUpdate(msgStatus.id, state, msg) + } + for (pmtStatus in msgStatus.payments) { + if (pmtStatus.id != "NOTPROVIDED") { + logger.warn("Unexpected payment status for ${msgStatus.id}.${pmtStatus.id}") + } else if (pmtStatus.code != null) { + val msg = pmtStatus.msg() + val state = when (pmtStatus.code) { + ExternalPaymentGroupStatusCode.ACSC -> StatusUpdate.success + ExternalPaymentGroupStatusCode.RJCT -> { + logger.error("Batch ${msgStatus.id} failed: $msg") + StatusUpdate.permanent_failure + } + else -> StatusUpdate.pending + } + db.initiated.batchStatusUpdate(msgStatus.id, state, msg) + } + for (txStatus in pmtStatus.transactions) { + val msg = txStatus.msg() + val state = when (txStatus.code) { + ExternalPaymentTransactionStatusCode.RJCT, + ExternalPaymentTransactionStatusCode.BLCK -> { + logger.error("Transaction ${txStatus.endToEndId} failed: $msg") + StatusUpdate.permanent_failure + } + else -> StatusUpdate.pending + } + db.initiated.txStatusUpdate(txStatus.endToEndId, null, state, msg) } } } } - +} + +/** Register an EBICS [payload] of [doc] into [db] */ +private suspend fun registerPayload( + db: Database, + cfg: NexusEbicsConfig, + payload: InputStream, + doc: OrderDoc +) { // Unzip payload if necessary when (doc) { OrderDoc.status, @@ -207,26 +260,24 @@ private suspend fun ingestPayload( try { payload.unzipEach { fileName, xml -> logger.trace("parse $fileName") - ingest(xml) + registerFile(db, cfg, xml, doc) } } catch (e: IOException) { throw Exception("Could not open any ZIP archive", e) } } - OrderDoc.acknowledgement -> ingest(payload) + OrderDoc.acknowledgement -> registerFile(db, cfg, payload, doc) } } /** - * Fetch and ingest banking records from [orders] using EBICS [client] starting from [pinnedStart] + * Fetch and register banking records from [orders] using EBICS [client] starting from [pinnedStart] * * If [pinnedStart] is null fetch new records. - * - * Return true if successful */ private suspend fun fetchEbicsDocuments( client: EbicsClient, - orders: List<EbicsOrder>, + orders: Collection<EbicsOrder>, pinnedStart: Instant?, ): Boolean { val lastExecutionTime: Instant? = pinnedStart @@ -248,7 +299,7 @@ private suspend fun fetchEbicsDocuments( lastExecutionTime, null ) { payload -> - ingestPayload(client.db, client.cfg, payload, doc) + registerPayload(client.db, client.cfg, payload, doc) } true } catch (e: Exception) { @@ -259,7 +310,9 @@ private suspend fun fetchEbicsDocuments( } } -class EbicsFetch: CliktCommand("Downloads and parse EBICS files from the bank and ingest them into the database") { +class EbicsFetch: CliktCommand() { + override fun help(context: Context) = "Downloads and parse EBICS files from the bank and register them into the database" + private val common by CommonOption() private val transient by transientOption() private val documents: Set<OrderDoc> by argument( @@ -285,7 +338,7 @@ class EbicsFetch: CliktCommand("Downloads and parse EBICS files from the bank an bankKeys ) val docs = if (documents.isEmpty()) OrderDoc.entries else documents.toList() - val orders = docs.map { cfg.dialect.downloadDoc(it, false) } + val requestedOrders = docs.map { cfg.dialect.downloadDoc(it, false) }.toSet() if (transient) { logger.info("Transient mode: fetching once and returning.") val pinnedStartVal = pinnedStart @@ -293,8 +346,8 @@ class EbicsFetch: CliktCommand("Downloads and parse EBICS files from the bank an logger.debug("Pinning start date to: {}", pinnedStartVal) dateToInstant(pinnedStartVal) } else null - if (!fetchEbicsDocuments(client, orders, pinnedStartArg)) { - throw Exception("Failed to fetch documents") + if (!fetchEbicsDocuments(client, requestedOrders, pinnedStartArg)) { + throw ProgramResult(1) } } else { val wssNotification = listenForNotification(client) @@ -303,20 +356,36 @@ class EbicsFetch: CliktCommand("Downloads and parse EBICS files from the bank an while (true) { val now = System.currentTimeMillis() if (nextFullRun < now) { + logger.info("Running at frequency") + // Always add HAC as it is never announced + val pendingOrders = mutableSetOf<EbicsOrder>(EbicsOrder.V3.HAC) + client.download(EbicsOrder.V3.HAA, null, null) { stream -> + val haa = EbicsAdministrative.parseHAA(stream) + logger.debug { + val orders = haa.orders.map(EbicsOrder::description).joinToString(", ") + "HAA: ${orders}" + } + pendingOrders.addAll(haa.orders) + } + // Only fetch requested and supported orders + val orders = requestedOrders intersect pendingOrders fetchEbicsDocuments(client, orders, null) nextFullRun = now + cfg.fetch.frequency.toMillis() } val delay = nextFullRun - now if (wssNotification == null) { - logger.info("Running at frequency") delay(delay) } else { val notifications = withTimeoutOrNull(delay) { wssNotification.receive() } if (notifications != null) { - logger.info("Running at real-time notifications reception") - fetchEbicsDocuments(client, notifications, null) + // Only fetch requested and supported orders + val orders = requestedOrders intersect notifications + if (orders.isNotEmpty()) { + logger.info("Running at real-time notifications reception") + fetchEbicsDocuments(client, notifications, null) + } } } } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt @@ -20,6 +20,7 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option @@ -144,7 +145,9 @@ private fun makePdf(privs: ClientPrivateKeysFile, cfg: NexusEbicsConfig) { /** * CLI class implementing the "ebics-setup" subcommand. */ -class EbicsSetup: CliktCommand("Set up the EBICS subscriber") { +class EbicsSetup: CliktCommand() { + override fun help(context: Context) = "Set up the EBICS subscriber" + private val common by CommonOption() private val forceKeysResubmission by option( help = "Resubmits all the keys to the bank" @@ -218,29 +221,78 @@ class EbicsSetup: CliktCommand("Set up the EBICS subscriber") { ebicsLogger, clientKeys, bankKeys - ).download(EbicsOrder.V3("HKD"), null, null) { stream -> - val hkd = EbicsAdministrative.parseHKD(stream) - val account = hkd.account - // TODO parse and check more information - if (account.currency != null && account.currency != cfg.currency) - logger.error("Expected CURRENCY '${cfg.currency}' from config got '${account.currency}' from bank") - if (account.iban != null && account.iban != cfg.account.iban) - logger.error("Expected IBAN '${cfg.account.iban}' from config got '${account.iban}' from bank") - if (account.name != null && account.name != cfg.account.name) - logger.warn("Expected NAME '${cfg.account.name}' from config got '${account.name}' from bank") - - logger.debug("User status: ${hkd.status.name} ${hkd.status.description}") - logger.debug("Supported orders:") - for (order in hkd.orders) { - logger.debug("${order.type}${order.params}: ${order.description}") + ).download(EbicsOrder.V3.HKD, null, null) { stream -> + val (partner, users) = EbicsAdministrative.parseHKD(stream) + val user = users.find { it -> it.id == cfg.ebicsUserId } + // Debug logging + logger.debug { + buildString { + if (partner.name != null || partner.accounts.isNotEmpty()) { + append("Partner Info: ") + if (partner.name != null) { + append("'") + append(partner.name) + append("' - ") + } + for ((iban, currency) in partner.accounts) { + append(iban) + append('_') + append(currency) + } + append('\n') + } + append("Supported orders:\n") + for ((order, description) in partner.orders) { + append("- ") + append(order.description()) + append(": ") + append(description) + append('\n') + } + if (user != null) { + append("Authorized orders:\n") + for ((order) in partner.orders) { + append("- ") + append(order.description()) + append('\n') + } + } + } + } + + // Check partner info match config + if (partner.name != null && partner.name != cfg.account.name) + logger.warn("Expected NAME '${cfg.account.name}' from config got '${partner.name}' from bank") + val account = partner.accounts.find { it.iban == cfg.account.iban } + if (account != null) { + if (account.currency != null && account.currency != cfg.currency) + logger.error("Expected CURRENCY '${cfg.currency}' from config got '${account.currency}' from bank") + } else if (partner.accounts.isNotEmpty()) { + val ibans = partner.accounts.map { it.iban }.joinToString(", ") + logger.error("Expected IBAN ${cfg.account.iban} from config got $ibans from bank") } - logger.debug("Authorized orders:") - for (order in hkd.permissions) { - logger.debug("${order.type}${order.params}") + + val requireOrders = cfg.dialect.orders() + + // Check partner support required orders + val unsupportedOrder = requireOrders subtract partner.orders.map { it.order } + if (unsupportedOrder.isNotEmpty()) { + logger.warn("Unsupported orders: {}", unsupportedOrder.map(EbicsOrder::description).joinToString(", ")) + } + + // Check user is authorized for required orders + if (user != null) { + val unauthorizedOrders = requireOrders subtract user.permissions subtract unsupportedOrder + if (unauthorizedOrders.isNotEmpty()) { + logger.warn("Unauthorized orders: {}", unauthorizedOrders.map(EbicsOrder::description).joinToString(", ")) + } + + logger.info("Subscriber status: {}", user.status.description) } } } } catch (e: Exception) { + // This can happen if HKD is not supported logger.warn("HKD failed: ${e.fmt()}") } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSubmit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSubmit.kt @@ -20,48 +20,53 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import kotlinx.coroutines.delay -import tech.libeufin.common.CommonOption -import tech.libeufin.common.Payto -import tech.libeufin.common.cliCmd -import tech.libeufin.common.fmt +import tech.libeufin.common.* import tech.libeufin.nexus.* -import tech.libeufin.nexus.db.InitiatedPayment -import tech.libeufin.nexus.ebics.EbicsClient -import java.time.Duration +import tech.libeufin.nexus.db.PaymentBatch +import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* import java.time.Instant import kotlin.time.toKotlinDuration +fun batchToPain001Msg(account: IbanAccountMetadata, batch: PaymentBatch): Pain001Msg { + return Pain001Msg( + messageId = batch.messageId, + timestamp = batch.creationDate, + debtor = account, + sum = batch.sum, + txs = batch.payments.map { payment -> + val payto = payment.creditor + Pain001Tx( + creditor = IbanAccountMetadata( + iban = payto.iban.value, + bic = payto.bic, + name = payto.receiverName!! + ), + amount = payment.amount, + subject = payment.subject, + endToEndId = payment.endToEndId + ) + } + ) +} + /** - * Submit an initiated [payment] using [client]. + * Submit an initiated payments [batch] using [client]. * - * Parse creditor IBAN account metadata then perform an EBICS direct credit. + * Parse creditor IBAN account metadata then perform an EBICS direct credit * * Returns the orderID */ -private suspend fun submitInitiatedPayment( +private suspend fun submitBatch( client: EbicsClient, - payment: InitiatedPayment + batch: PaymentBatch ): String { - val creditAccount = try { - val payto = Payto.parse(payment.creditPaytoUri).expectIban() - IbanAccountMetadata( - iban = payto.iban.value, - bic = payto.bic, - name = payto.receiverName!! - ) - } catch (e: Exception) { - throw e // TODO handle payto error - } - + val msg = batchToPain001Msg(client.cfg.account, batch) val xml = createPain001( - requestUid = payment.requestUid, - initiationTimestamp = payment.initiationTime, - amount = payment.amount, - creditAccount = creditAccount, - debitAccount = client.cfg.account, - wireTransferSubject = payment.wireTransferSubject, + msg = msg, dialect = client.cfg.dialect ) return client.upload( @@ -72,23 +77,29 @@ private suspend fun submitInitiatedPayment( /** Submit all pending initiated payments using [client] */ private suspend fun submitBatch(client: EbicsClient) { - client.db.initiated.submittable(client.cfg.currency).forEach { - logger.debug("Submitting payment '${it.requestUid}'") - runCatching { submitInitiatedPayment(client, it) }.fold( + // Create batch if necessary + client.db.initiated.batch(Instant.now(), randEbicsId()) + // Send submitable batches + client.db.initiated.submittable(client.cfg.currency).forEach { batch -> + logger.debug("Submitting batch {}", batch.messageId) + runCatching { submitBatch(client, batch) }.fold( onSuccess = { orderId -> - client.db.initiated.submissionSuccess(it.id, Instant.now(), orderId) - logger.info("Payment '${it.requestUid}' submitted") + client.db.initiated.batchSubmissionSuccess(batch.id, Instant.now(), orderId) + val transactions = batch.payments.map { it.endToEndId }.joinToString(",") + logger.info("Batch ${batch.messageId} submitted as order $orderId: $transactions") }, onFailure = { e -> - client.db.initiated.submissionFailure(it.id, Instant.now(), e.message) - logger.error("Payment '${it.requestUid}' submission failure: ${e.fmt()}") + client.db.initiated.batchSubmissionFailure(batch.id, Instant.now(), e.message) + logger.error("Batch ${batch.messageId} submission failure: ${e.fmt()}") throw e } ) } } -class EbicsSubmit : CliktCommand("Submits pending initiated payments found in the database") { +class EbicsSubmit : CliktCommand() { + override fun help(context: Context) = "Submits pending initiated payments found in the database" + private val common by CommonOption() private val transient by transientOption() private val ebicsLog by ebicsLogOption() diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/InitiatePayment.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/InitiatePayment.kt @@ -19,6 +19,7 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.convert import com.github.ajalt.clikt.parameters.groups.provideDelegate @@ -26,12 +27,15 @@ import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.common.* import tech.libeufin.nexus.db.InitiatedPayment +import tech.libeufin.nexus.ebics.randEbicsId import tech.libeufin.nexus.logger import tech.libeufin.nexus.nexusConfig import tech.libeufin.nexus.withDb import java.time.Instant -class InitiatePayment: CliktCommand("Initiate an outgoing payment") { +class InitiatePayment: CliktCommand() { + override fun help(context: Context) = "Initiate an outgoing payment" + private val common by CommonOption() private val amount by option( "--amount", @@ -41,9 +45,10 @@ class InitiatePayment: CliktCommand("Initiate an outgoing payment") { "--subject", help = "The payment subject, payto 'message' parameter takes the precedence" ) - private val requestUid by option( + private val endToEndId by option( + "--end-to-end-id", "--request-uid", - help = "The payment request UID" + help = "The payment end-to-end UID" ) private val payto by argument( help = "The credited account IBAN payto URI" @@ -59,19 +64,14 @@ class InitiatePayment: CliktCommand("Initiate an outgoing payment") { "Wrong currency: expected ${cfg.currency} got ${amount.currency}" } - val requestUid = requestUid ?: run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } - db.initiated.create( InitiatedPayment( id = -1, amount = amount, - wireTransferSubject = subject, - creditPaytoUri = payto.toString(), + subject = subject, + creditor = payto, initiationTime = Instant.now(), - requestUid = requestUid + endToEndId = endToEndId ?: randEbicsId() ) ) } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Serve.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Serve.kt @@ -20,6 +20,7 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag @@ -33,7 +34,9 @@ import tech.libeufin.nexus.nexusConfig import tech.libeufin.nexus.withDb -class Serve : CliktCommand("Run libeufin-nexus HTTP server", name = "serve") { +class Serve : CliktCommand("serve") { + override fun help(context: Context) = "Run libeufin-nexus HTTP server" + private val common by CommonOption() private val check by option( help = "Check whether an API is in use (if it's useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1" diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt @@ -20,6 +20,7 @@ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.convert @@ -29,13 +30,15 @@ import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.enum -import kotlinx.coroutines.delay import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* import java.time.Instant -class Wss: CliktCommand("Listen to EBICS instant notification over websocket") { +class Wss: CliktCommand() { + override fun help(context: Context) = "Listen to EBICS instant notification over websocket" + private val common by CommonOption() private val ebicsLog by ebicsLogOption() @@ -55,7 +58,7 @@ class Wss: CliktCommand("Listen to EBICS instant notification over websocket") { val wssNotifications = listenForNotification(client) if (wssNotifications != null) { while (true) { - val notifications = wssNotifications.receive() + wssNotifications.receive() logger.debug("{}", wssNotifications) } } @@ -63,7 +66,9 @@ class Wss: CliktCommand("Listen to EBICS instant notification over websocket") { } } -class FakeIncoming: CliktCommand("Genere a fake incoming payment") { +class FakeIncoming: CliktCommand() { + override fun help(context: Context) = "Genere a fake incoming payment" + private val common by CommonOption() private val amount by option( "--amount", @@ -85,26 +90,23 @@ class FakeIncoming: CliktCommand("Genere a fake incoming payment") { require(amount.currency == cfg.currency) { "Wrong currency: expected ${cfg.currency} got ${amount.currency}" } - - val bankId = run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } - ingestIncomingPayment(db, cfg.ebics.ingest, + registerIncomingPayment(db, cfg.ebics.ingest, IncomingPayment( amount = amount, - debitPaytoUri = payto.toString(), - wireTransferSubject = subject, + debtorPayto = payto, + subject = subject, executionTime = Instant.now(), - bankId = bankId + bankId = randEbicsId() ) ) } } } -class TxCheck: CliktCommand("Check transaction semantic") { +class TxCheck: CliktCommand() { + override fun help(context: Context) = "Check transaction semantic" + private val common by CommonOption() override fun run() = cliCmd(logger, common.log) { @@ -130,7 +132,9 @@ enum class ListKind { } } -class EbicsDownload: CliktCommand("Perform EBICS requests", name = "ebics-btd") { +class EbicsDownload: CliktCommand("ebics-btd") { + override fun help(context: Context) = "Perform EBICS requests" + private val common by CommonOption() private val type by option().default("BTD") private val name by option() @@ -189,7 +193,9 @@ class EbicsDownload: CliktCommand("Perform EBICS requests", name = "ebics-btd") } } -class ListCmd: CliktCommand("List nexus transactions", name = "list") { +class ListCmd: CliktCommand("list") { + override fun help(context: Context) = "List nexus transactions" + private val common by CommonOption() private val kind: ListKind by argument( help = "Which list to print", @@ -271,10 +277,12 @@ class ListCmd: CliktCommand("List nexus transactions", name = "list") { } } -class TestingCmd : CliktCommand("Testing helper commands", name = "testing") { +class TestingCmd : CliktCommand("testing") { init { subcommands(FakeIncoming(), ListCmd(), EbicsDownload(), TxCheck(), Wss()) } + override fun help(context: Context) = "Testing helper commands" + override fun run() = Unit } \ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt @@ -22,34 +22,70 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import org.slf4j.LoggerFactory import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TransferStatusState +import tech.libeufin.common.IbanPayto import tech.libeufin.common.db.DatabaseConfig import tech.libeufin.common.db.DbPool import tech.libeufin.common.db.watchNotifications import java.time.Instant -/** - * Minimal set of information to initiate a new payment in - * the database. - */ +/** Batch of initiated outgoing payment to sent together */ +data class PaymentBatch( + val id: Long, + val messageId: String, + val creationDate: Instant, + val sum: TalerAmount, + val payments: List<InitiatedPayment>, +) + +/** Initiated outgoing transaction */ data class InitiatedPayment( val id: Long, val amount: TalerAmount, - val wireTransferSubject: String, - val creditPaytoUri: String, + val subject: String, + val creditor: IbanPayto, val initiationTime: Instant, - val requestUid: String + val endToEndId: String ) +enum class StatusUpdate { + pending, + transient_failure, + permanent_failure, + success +} + +/** Outgoing transactions and batches submission status */ enum class SubmissionState { + // Initiated but not yet submitted unsubmitted, + // Submission failed, retry possible transient_failure, + // Submission succeed, pending settltment + pending, + // Definitive failure, will never succeed permanent_failure, - success + // Definitive success, booked and settled + success, + // Late failure after a success, happens when a payment is returned + late_failure; + + companion object { + val SETTLED = listOf(SubmissionState.success, SubmissionState.permanent_failure, SubmissionState.late_failure) + val PENDING = listOf(SubmissionState.unsubmitted, SubmissionState.pending) + } + + fun toTransferStatus(): TransferStatusState { + return when (this) { + SubmissionState.unsubmitted, SubmissionState.pending -> TransferStatusState.pending + SubmissionState.transient_failure -> TransferStatusState.transient_failure + SubmissionState.permanent_failure -> TransferStatusState.permanent_failure + SubmissionState.success, SubmissionState.late_failure -> TransferStatusState.success + } + } } -/** - * Collects database connection steps and any operation on the Nexus tables. - */ +/** Collects database connection steps and any operation on the Nexus tables */ class Database(dbConfig: DatabaseConfig, val bankCurrency: String): DbPool(dbConfig, "libeufin_nexus") { val payment = PaymentDAO(this) val initiated = InitiatedDAO(this) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/ExchangeDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/ExchangeDAO.kt @@ -35,7 +35,7 @@ class ExchangeDAO(private val db: Database) { ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,debit_payto_uri + ,debit_payto ,type ,reserve_public_key ,account_pub @@ -49,14 +49,14 @@ class ExchangeDAO(private val db: Database) { row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getString("debit_payto_uri"), + debit_account = it.getString("debit_payto"), reserve_pub = EddsaPublicKey(it.getBytes("reserve_public_key")), ) TalerIncomingType.kyc -> IncomingKycAuthTransaction( row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getString("debit_payto_uri"), + debit_account = it.getString("debit_payto"), account_pub = EddsaPublicKey(it.getBytes("account_pub")), ) TalerIncomingType.wad -> throw UnsupportedOperationException() @@ -73,7 +73,7 @@ class ExchangeDAO(private val db: Database) { ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,credit_payto_uri + ,credit_payto ,wtid ,exchange_base_url FROM talerable_outgoing_transactions @@ -84,7 +84,7 @@ class ExchangeDAO(private val db: Database) { row_id = it.getLong("outgoing_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.bankCurrency), - credit_account = it.getString("credit_payto_uri"), + credit_account = it.getString("credit_payto"), wtid = ShortHashCode(it.getBytes("wtid")), exchange_base_url = it.getString("exchange_base_url") ) @@ -100,7 +100,7 @@ class ExchangeDAO(private val db: Database) { /** Perform a Taler transfer */ suspend fun transfer( req: TransferRequest, - bankId: String, + endToEndId: String, timestamp: Instant ): TransferResult = db.serializable( """ @@ -124,7 +124,7 @@ class ExchangeDAO(private val db: Database) { setInt(5, req.amount.frac) setString(6, req.exchange_base_url.url) setString(7, req.credit_account.canonical) - setString(8, bankId) + setString(8, endToEndId) setLong(9, timestamp.micros()) one { when { @@ -147,10 +147,10 @@ class ExchangeDAO(private val db: Database) { ,exchange_base_url ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,submitted - ,credit_payto_uri + ,credit_payto ,initiation_time - ,failure_message + ,status + ,status_msg FROM transfer_operations JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) WHERE initiated_outgoing_transaction_id=? @@ -159,17 +159,12 @@ class ExchangeDAO(private val db: Database) { setLong(1, id) oneOrNull { TransferStatus( - status = when (it.getEnum<SubmissionState>("submitted")) { - SubmissionState.unsubmitted -> TransferStatusState.pending - SubmissionState.transient_failure -> TransferStatusState.transient_failure - SubmissionState.permanent_failure -> TransferStatusState.permanent_failure - SubmissionState.success -> TransferStatusState.success - }, - status_msg = it.getString("failure_message"), + status = it.getEnum<SubmissionState>("status").toTransferStatus(), + status_msg = it.getString("status_msg"), amount = it.getAmount("amount", db.bankCurrency), origin_exchange_url = it.getString("exchange_base_url"), wtid = ShortHashCode(it.getBytes("wtid")), - credit_account = it.getString("credit_payto_uri"), + credit_account = it.getString("credit_payto"), timestamp = it.getTalerTimestamp("initiation_time"), ) } @@ -186,39 +181,39 @@ class ExchangeDAO(private val db: Database) { initiated_outgoing_transaction_id ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,submitted - ,credit_payto_uri + ,status + ,credit_payto ,initiation_time FROM transfer_operations JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) - WHERE ${if (params.status != null) "submitted=?::submission_state AND" else ""} + WHERE ${ + when (params.status) { + null -> "" + TransferStatusState.pending -> "(status=?::submission_state OR status=?::submission_state) AND" + else -> "status=?::submission_state AND" + } + } """, { - val state = when (params.status) { - TransferStatusState.pending -> SubmissionState.unsubmitted - TransferStatusState.transient_failure -> SubmissionState.transient_failure - TransferStatusState.permanent_failure -> SubmissionState.permanent_failure - TransferStatusState.success -> SubmissionState.success - null -> null - } - if (state != null) { - setString(1, state.name) - 1 - } else { - 0 + when (params.status) { + null -> 0 + TransferStatusState.pending -> { + setString(1, SubmissionState.pending.name) + setString(2, SubmissionState.unsubmitted.name) + 2 + } + else -> { + setString(1, params.status?.name) + 1 + } } } ) { TransferListStatus( row_id = it.getLong("initiated_outgoing_transaction_id"), - status = when (it.getEnum<SubmissionState>("submitted")) { - SubmissionState.unsubmitted -> TransferStatusState.pending - SubmissionState.transient_failure -> TransferStatusState.transient_failure - SubmissionState.permanent_failure -> TransferStatusState.permanent_failure - SubmissionState.success -> TransferStatusState.success - }, + status = it.getEnum<SubmissionState>("status").toTransferStatus(), amount = it.getAmount("amount", db.bankCurrency), - credit_account = it.getString("credit_payto_uri"), + credit_account = it.getString("credit_payto"), timestamp = it.getTalerTimestamp("initiation_time"), ) } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt @@ -20,15 +20,17 @@ package tech.libeufin.nexus.db import tech.libeufin.common.asInstant -import tech.libeufin.common.db.all -import tech.libeufin.common.db.getAmount -import tech.libeufin.common.db.oneOrNull -import tech.libeufin.common.db.oneUniqueViolation +import tech.libeufin.common.db.* import tech.libeufin.common.micros +import tech.libeufin.nexus.iso20022.OutgoingPayment import java.time.Instant /** Data access logic for initiated outgoing payments */ class InitiatedDAO(private val db: Database) { + private val UNSETTLED_FILTER = + "status NOT IN (${SubmissionState.SETTLED.map { "'$it'" }.joinToString(",")})" + private val PENDING_FILTER = + "status IN (${SubmissionState.PENDING.map { "'$it'" }.joinToString(",")})" /** Outgoing payments initiation result */ sealed interface PaymentInitiationResult { @@ -36,189 +38,330 @@ class InitiatedDAO(private val db: Database) { data object RequestUidReuse: PaymentInitiationResult } - /** Register a new pending payment in the database */ - suspend fun create(paymentData: InitiatedPayment): PaymentInitiationResult = db.serializable( + /** Initiate a new payment */ + suspend fun create(payment: InitiatedPayment): PaymentInitiationResult = db.serializable( """ INSERT INTO initiated_outgoing_transactions ( - amount - ,wire_transfer_subject - ,credit_payto_uri + amount + ,subject + ,credit_payto ,initiation_time - ,request_uid + ,end_to_end_id ) VALUES ((?,?)::taler_amount,?,?,?,?) RETURNING initiated_outgoing_transaction_id """ ) { // TODO check payto uri - setLong(1, paymentData.amount.value) - setInt(2, paymentData.amount.frac) - setString(3, paymentData.wireTransferSubject) - setString(4, paymentData.creditPaytoUri) - setLong(5, paymentData.initiationTime.micros()) - setString(6, paymentData.requestUid) + setLong(1, payment.amount.value) + setInt(2, payment.amount.frac) + setString(3, payment.subject) + setString(4, payment.creditor.toString()) + setLong(5, payment.initiationTime.micros()) + setString(6, payment.endToEndId) oneUniqueViolation(PaymentInitiationResult.RequestUidReuse) { PaymentInitiationResult.Success(it.getLong("initiated_outgoing_transaction_id")) } } - /** Register EBICS submission success */ - suspend fun submissionSuccess( + /** Register submission success of order [orderId] for batch [id] at [timestamp] */ + suspend fun batchSubmissionSuccess( id: Long, timestamp: Instant, orderId: String - ) = db.serializable( - """ - UPDATE initiated_outgoing_transactions SET - submitted = 'success'::submission_state - ,last_submission_time = ? - ,failure_message = NULL - ,order_id = ? - ,submission_counter = submission_counter + 1 - WHERE initiated_outgoing_transaction_id = ? - """ - ) { - setLong(1, timestamp.micros()) - setString(2, orderId) - setLong(3, id) - execute() + ) = db.serializableTransaction { tx -> + // Update batch status + val updated = tx.withStatement( + """ + UPDATE initiated_outgoing_batches + SET status = 'pending' + ,submission_date = ? + ,status_msg = NULL + ,order_id = ? + ,submission_counter = submission_counter + 1 + WHERE initiated_outgoing_batch_id = ? AND order_id IS NULL + """ + ) { + setLong(1, timestamp.micros()) + setString(2, orderId) + setLong(3, id) + executeUpdate() + } + if (updated > 0) { + // Update unsettled batch's transaction status + tx.withStatement( + """ + UPDATE initiated_outgoing_transactions + SET status = 'pending', status_msg = NULL + WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER + """ + ) { + setLong(1, id) + execute() + } + } } - /** Register EBICS submission failure */ - suspend fun submissionFailure( + /** Register submission failure with [msg] for batch [id] at [timestamp]*/ + suspend fun batchSubmissionFailure( id: Long, timestamp: Instant, msg: String? - ) = db.serializable( - """ - UPDATE initiated_outgoing_transactions SET - submitted = 'transient_failure'::submission_state - ,last_submission_time = ? - ,failure_message = ? - ,submission_counter = submission_counter + 1 - WHERE initiated_outgoing_transaction_id = ? - """ - ) { - setLong(1, timestamp.micros()) - setString(2, msg) - setLong(3, id) - execute() + ) = db.serializableTransaction { tx -> + // Update batch status + tx.withStatement( + """ + UPDATE initiated_outgoing_batches + SET status = 'transient_failure' + ,submission_date = ? + ,status_msg = ? + ,submission_counter = submission_counter + 1 + WHERE initiated_outgoing_batch_id = ? + """ + ) { + setLong(1, timestamp.micros()) + setString(2, msg) + setLong(3, id) + execute() + } + // Update unsettled batch's transaction status + tx.withStatement( + """ + UPDATE initiated_outgoing_transactions + SET status = 'transient_failure', status_msg = ? + WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER + """ + ) { + setString(1, msg) + setLong(2, id) + execute() + } } - /** Register EBICS log status message */ - suspend fun logMessage(orderId: String, msg: String) = db.serializable( - """ - UPDATE initiated_outgoing_transactions SET failure_message = ? - WHERE order_id = ? - """ - ) { - setString(1, msg) - setString(2, orderId) - execute() + /** Register order step [msg] for [orderId] */ + suspend fun orderStep(orderId: String, msg: String) = db.serializableTransaction { tx -> + // Update pending batch status + val batchId = tx.withStatement( + """ + UPDATE initiated_outgoing_batches + SET status = 'pending', status_msg = ? + WHERE order_id = ? AND $PENDING_FILTER + RETURNING initiated_outgoing_batch_id + """ + ) { + setString(1, msg) + setString(2, orderId) + oneOrNull { it.getLong(1) } + } + if (batchId != null) { + // Update pending batch's transaction status + tx.withStatement( + """ + UPDATE initiated_outgoing_transactions + SET status = 'pending', status_msg = ? + WHERE initiated_outgoing_batch_id = ? AND $PENDING_FILTER + """ + ) { + setString(1, msg) + setLong(2, batchId) + execute() + } + } } - /** Register EBICS log success and return request_uid if found */ - suspend fun logSuccess(orderId: String): String? = db.serializable( - """ - SELECT request_uid FROM initiated_outgoing_transactions - WHERE order_id = ? - """ - ) { - setString(1, orderId) - oneOrNull { it.getString(1) } + /** Register order success for [orderId] and return message_id if found */ + suspend fun orderSuccess(orderId: String): String? = db.serializableTransaction { tx -> + // Update batch status + val result = tx.withStatement( + """ + UPDATE initiated_outgoing_batches + SET status = 'success' + WHERE order_id = ? + RETURNING initiated_outgoing_batch_id, message_id + """ + ) { + setString(1, orderId) + oneOrNull { + Pair( + it.getLong("initiated_outgoing_batch_id"), + it.getString("message_id") + ) + } + } + if (result == null) return@serializableTransaction null + val (batchId, messageId) = result + // Update unsettled batch's transaction status + tx.withStatement( + """ + UPDATE initiated_outgoing_transactions + SET status = 'pending' + WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER + """ + ) { + setLong(1, batchId) + execute() + } + messageId } - /** Register EBICS log failure and return request_uid and previous message if found */ - suspend fun logFailure(orderId: String): Pair<String, String?>? = db.serializable( - """ - UPDATE initiated_outgoing_transactions - SET submitted = 'permanent_failure'::submission_state - WHERE order_id = ? - RETURNING request_uid, failure_message - """ - ) { - setString(1, orderId) - oneOrNull { Pair(it.getString(1), it.getString(2)) } + /** Register order failure for [orderId] and return message_id and previous status_msg if found */ + suspend fun orderFailure(orderId: String): Pair<String, String?>? = db.serializableTransaction { tx -> + // Update batch status + val result = tx.withStatement( + """ + UPDATE initiated_outgoing_batches + SET status = 'permanent_failure' + WHERE order_id = ? + RETURNING initiated_outgoing_batch_id, message_id, status_msg + """ + ) { + setString(1, orderId) + oneOrNull { + Triple( + it.getLong("initiated_outgoing_batch_id"), + it.getString("message_id"), + it.getString("status_msg") + ) + } + } + if (result == null) return@serializableTransaction null + val (batchId, messageId, msg) = result + // Update batch's transaction status + tx.withStatement( + """ + UPDATE initiated_outgoing_transactions + SET status = 'permanent_failure' + WHERE initiated_outgoing_batch_id = ? + """ + ) { + setLong(1, batchId) + execute() + } + Pair(messageId, msg) } - /** Register bank status message */ - suspend fun bankMessage(requestUID: String, msg: String) = db.serializable( - """ - UPDATE initiated_outgoing_transactions - SET failure_message = ? - WHERE request_uid = ? - """ - ) { - setString(1, msg) - setString(2, requestUID) + /** Register payment status [state] with [msg] for batch [msgId] */ + suspend fun batchStatusUpdate(msgId: String, state: StatusUpdate, msg: String?) = db.serializable( + "SELECT FROM batch_status_update(?,?::submission_state,?)" + ) { + setString(1, msgId) + setString(2, state.name) + setString(3, msg) execute() } - /** Register bank failure */ - suspend fun bankFailure(requestUID: String, msg: String) = db.serializable( - """ - UPDATE initiated_outgoing_transactions SET - submitted = 'permanent_failure'::submission_state - ,failure_message = ? - WHERE request_uid = ? - """ + /** Register payment status [state] with [msg] for transaction [endToEndId] in batch [msgId] */ + suspend fun txStatusUpdate(endToEndId: String, msgId: String?, state: StatusUpdate, msg: String) = db.serializable( + "SELECT FROM tx_status_update(?,?,?::submission_state,?)" ) { - setString(1, msg) - setString(2, requestUID) + setString(1, endToEndId) + setString(2, msgId) + setString(3, state.name) + setString(4, msg) execute() } - /** Register reversal */ - suspend fun reversal(requestUID: String, msg: String) = db.serializable( + /** Unsettled initiated payment in batch [msgId] */ + suspend fun unsettledTxInBatch(msgId: String, executionTime: Instant) = db.serializable( """ - UPDATE initiated_outgoing_transactions SET - submitted = 'permanent_failure'::submission_state - ,failure_message = ? - WHERE request_uid = ? + SELECT end_to_end_id + ,(amount).val as amount_val + ,(amount).frac as amount_frac + ,subject + ,credit_payto + FROM initiated_outgoing_transactions + JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) + WHERE message_id = ? + AND initiated_outgoing_transactions.$UNSETTLED_FILTER """ - ) { - setString(1, msg) - setString(2, requestUID) - execute() + ) { + setString(1, msgId) + all { + OutgoingPayment( + endToEndId = it.getString("end_to_end_id"), + msgId = msgId, + amount = it.getAmount("amount", db.bankCurrency), + subject = it.getString("subject"), + executionTime = executionTime, + creditorPayto = it.getIbanPayto("credit_payto") + ) + } + } + + /** Group unbatched transaction into a single batch */ + suspend fun batch(timestamp: Instant, ebicsId: String) { + db.serializable("SELECT FROM batch_outgoing_transactions(?, ?)") { + setLong(1, timestamp.micros()) + setString(2, ebicsId) + execute() + } } /** List every initiated payment pending submission in the order they should be submitted */ - suspend fun submittable(currency: String): List<InitiatedPayment> { + suspend fun submittable(currency: String): List<PaymentBatch> { val selectPart = """ - SELECT - initiated_outgoing_transaction_id - ,(amount).val as amount_val - ,(amount).frac as amount_frac - ,wire_transfer_subject - ,credit_payto_uri - ,initiation_time - ,request_uid - FROM initiated_outgoing_transactions + SELECT initiated_outgoing_batch_id, message_id, creation_date, (sum).val as sum_val, (sum).frac as sum_frac + FROM initiated_outgoing_batches """ - // We want to maximize the number of successfully submitted transactions in the event - // of a malformed transaction or a persistent error classified as transient. We send - // the unsubmitted transactions first, starting with the oldest by creation time. - // This is the happy path, giving every transaction a chance while being fair on the - // basis of creation date. - // Then we retry the failed transaction, starting with the oldest by submission time. - // This the bad path retrying each failed transaction applying a rotation based on - // resubmission time. - return db.serializable( - """ - ($selectPart WHERE submitted='unsubmitted' ORDER BY initiation_time) - UNION ALL - ($selectPart WHERE submitted='transient_failure' ORDER BY last_submission_time) - """ - ) { - all { - InitiatedPayment( - id = it.getLong("initiated_outgoing_transaction_id"), - amount = it.getAmount("amount", currency), - creditPaytoUri = it.getString("credit_payto_uri"), - wireTransferSubject = it.getString("wire_transfer_subject"), - initiationTime = it.getLong("initiation_time").asInstant(), - requestUid = it.getString("request_uid") - ) + return db.serializableTransaction { tx -> + // We want to maximize the number of successfully submitted batches in the event + // of a malformed transaction or a persistent error classified as transient. We send + // the unsubmitted batches first, starting with the oldest by creation time. + // This is the happy path, giving every batch a chance while being fair on the + // basis of creation date. + // Then we retry the failed batches, starting with the oldest by submission time. + // This the bad path retrying each failed batch applying a rotation based on + // resubmission time. + val batches = tx.withStatement( + """ + ($selectPart WHERE status='unsubmitted' ORDER BY creation_date) + UNION ALL + ($selectPart WHERE status='transient_failure' ORDER BY submission_date) + """ + ) { + all { + PaymentBatch( + id = it.getLong("initiated_outgoing_batch_id"), + messageId = it.getString("message_id"), + creationDate = it.getLong("creation_date").asInstant(), + sum = it.getAmount("sum", currency), + payments = emptyList() + ) + } + }.map { it.id to Pair(it, mutableListOf<InitiatedPayment>()) }.toMap() + + // Then load transactions + tx.withStatement( + """ + SELECT + initiated_outgoing_transaction_id + ,(amount).val as amount_val + ,(amount).frac as amount_frac + ,subject + ,credit_payto + ,initiated_outgoing_transactions.initiation_time + ,end_to_end_id + ,initiated_outgoing_batch_id + FROM initiated_outgoing_transactions + JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) + WHERE initiated_outgoing_batches.status IN ('unsubmitted', 'transient_failure') + """ + ) { + all { + val payment = InitiatedPayment( + id = it.getLong("initiated_outgoing_transaction_id"), + amount = it.getAmount("amount", currency), + creditor = it.getIbanPayto("credit_payto"), + subject = it.getString("subject"), + initiationTime = it.getLong("initiation_time").asInstant(), + endToEndId = it.getString("end_to_end_id") + ) + val batchId = it.getLong("initiated_outgoing_batch_id") + batches[batchId]!!.second.add(payment) + Unit + } } + + batches.values.map { (it, payments) -> it.copy(payments = payments) } } } } \ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt @@ -21,10 +21,10 @@ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* -import tech.libeufin.nexus.IncomingPayment -import tech.libeufin.nexus.OutgoingPayment -import java.time.Instant +import tech.libeufin.nexus.iso20022.IncomingPayment +import tech.libeufin.nexus.iso20022.OutgoingPayment import java.sql.Types +import java.time.Instant /** Data access logic for incoming & outgoing payments */ class PaymentDAO(private val db: Database) { @@ -37,26 +37,27 @@ class PaymentDAO(private val db: Database) { /** Register an outgoing payment reconciling it with its initiated payment counterpart if present */ suspend fun registerOutgoing( - paymentData: OutgoingPayment, + payment: OutgoingPayment, wtid: ShortHashCode?, baseUrl: ExchangeUrl?, ): OutgoingRegistrationResult = db.serializable( """ SELECT out_tx_id, out_initiated, out_found - FROM register_outgoing((?,?)::taler_amount,?,?,?,?,?,?) + FROM register_outgoing((?,?)::taler_amount,?,?,?,?,?,?,?) """ ) { - val executionTime = paymentData.executionTime.micros() - - setLong(1, paymentData.amount.value) - setInt(2, paymentData.amount.frac) - setString(3, paymentData.wireTransferSubject) + val executionTime = payment.executionTime.micros() + + setLong(1, payment.amount.value) + setInt(2, payment.amount.frac) + setString(3, payment.subject) setLong(4, executionTime) - setString(5, paymentData.creditPaytoUri) - setString(6, paymentData.messageId) + setString(5, payment.creditorPayto.toString()) + setString(6, payment.endToEndId) setBytes(7, wtid?.raw) setString(8, baseUrl?.url) - + setString(9, payment.msgId) + one { OutgoingRegistrationResult( it.getLong("out_tx_id"), @@ -75,24 +76,26 @@ class PaymentDAO(private val db: Database) { /** Register an incoming payment and bounce it */ suspend fun registerMalformedIncoming( - paymentData: IncomingPayment, + payment: IncomingPayment, bounceAmount: TalerAmount, + bounceEndToEndId: String, timestamp: Instant ): IncomingBounceRegistrationResult = db.serializable( """ SELECT out_found, out_tx_id, out_bounce_id - FROM register_incoming_and_bounce((?,?)::taler_amount,?,?,?,?,(?,?)::taler_amount,?) + FROM register_and_bounce_incoming((?,?)::taler_amount,?,?,?,?,(?,?)::taler_amount,?,?) """ ) { - setLong(1, paymentData.amount.value) - setInt(2, paymentData.amount.frac) - setString(3, paymentData.wireTransferSubject) - setLong(4, paymentData.executionTime.micros()) - setString(5, paymentData.debitPaytoUri) - setString(6, paymentData.bankId) + setLong(1, payment.amount.value) + setInt(2, payment.amount.frac) + setString(3, payment.subject) + setLong(4, payment.executionTime.micros()) + setString(5, payment.debtorPayto.toString()) + setString(6, payment.bankId) setLong(7, bounceAmount.value) setInt(8, bounceAmount.frac) setLong(9, timestamp.micros()) + setString(10, bounceEndToEndId) one { IncomingBounceRegistrationResult( it.getLong("out_tx_id"), @@ -110,21 +113,21 @@ class PaymentDAO(private val db: Database) { /** Register an talerable incoming payment */ suspend fun registerTalerableIncoming( - paymentData: IncomingPayment, + payment: IncomingPayment, metadata: TalerIncomingMetadata ): IncomingRegistrationResult = db.serializable( """ SELECT out_reserve_pub_reuse, out_found, out_tx_id - FROM register_incoming_and_talerable((?,?)::taler_amount,?,?,?,?,?::taler_incoming_type,?,?) + FROM register_incoming((?,?)::taler_amount,?,?,?,?,?::taler_incoming_type,?,?) """ ) { - val executionTime = paymentData.executionTime.micros() - setLong(1, paymentData.amount.value) - setInt(2, paymentData.amount.frac) - setString(3, paymentData.wireTransferSubject) + val executionTime = payment.executionTime.micros() + setLong(1, payment.amount.value) + setInt(2, payment.amount.frac) + setString(3, payment.subject) setLong(4, executionTime) - setString(5, paymentData.debitPaytoUri) - setString(6, paymentData.bankId) + setString(5, payment.debtorPayto.toString()) + setString(6, payment.bankId) setString(7, metadata.type.name) when (metadata.type) { TalerIncomingType.reserve -> { @@ -150,20 +153,20 @@ class PaymentDAO(private val db: Database) { /** Register an incoming payment */ suspend fun registerIncoming( - paymentData: IncomingPayment + payment: IncomingPayment ): IncomingRegistrationResult.Success = db.serializable( """ SELECT out_found, out_tx_id - FROM register_incoming((?,?)::taler_amount,?,?,?,?) + FROM register_incoming((?,?)::taler_amount,?,?,?,?,NULL,NULL,NULL) """ - ) { - val executionTime = paymentData.executionTime.micros() - setLong(1, paymentData.amount.value) - setInt(2, paymentData.amount.frac) - setString(3, paymentData.wireTransferSubject) + ) { + val executionTime = payment.executionTime.micros() + setLong(1, payment.amount.value) + setInt(2, payment.amount.frac) + setString(3, payment.subject) setLong(4, executionTime) - setString(5, paymentData.debitPaytoUri) - setString(6, paymentData.bankId) + setString(5, payment.debtorPayto.toString()) + setString(6, payment.bankId) one { IncomingRegistrationResult.Success( it.getLong("out_tx_id"), @@ -178,20 +181,20 @@ class PaymentDAO(private val db: Database) { ): List<RevenueIncomingBankTransaction> = db.poolHistoryGlobal(params, db::listenRevenue, """ SELECT - incoming_transaction_id + incoming_transaction_id ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac - ,debit_payto_uri - ,wire_transfer_subject + ,debit_payto + ,subject FROM incoming_transactions WHERE """, "incoming_transaction_id") { RevenueIncomingBankTransaction( row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.bankCurrency), - debit_account = it.getString("debit_payto_uri"), - subject = it.getString("wire_transfer_subject") + debit_account = it.getString("debit_payto"), + subject = it.getString("subject") ) } @@ -199,11 +202,11 @@ class PaymentDAO(private val db: Database) { suspend fun metadataIncoming(): List<IncomingTxMetadata> = db.serializable( """ SELECT - (amount).val as amount_val + (amount).val as amount_val ,(amount).frac AS amount_frac - ,wire_transfer_subject + ,subject ,execution_time - ,debit_payto_uri + ,debit_payto ,bank_id ,type ,reserve_public_key @@ -218,8 +221,8 @@ class PaymentDAO(private val db: Database) { IncomingTxMetadata( date = it.getLong("execution_time").asInstant(), amount = it.getDecimal("amount"), - subject = it.getString("wire_transfer_subject"), - debtor = it.getString("debit_payto_uri"), + subject = it.getString("subject"), + debtor = it.getString("debit_payto"), id = it.getString("bank_id"), talerable = when (type) { null -> null @@ -235,12 +238,12 @@ class PaymentDAO(private val db: Database) { suspend fun metadataOutgoing(): List<OutgoingTxMetadata> = db.serializable( """ SELECT - (amount).val as amount_val + (amount).val as amount_val ,(amount).frac AS amount_frac - ,wire_transfer_subject + ,subject ,execution_time - ,credit_payto_uri - ,message_id + ,credit_payto + ,end_to_end_id ,wtid ,exchange_base_url FROM outgoing_transactions @@ -252,9 +255,9 @@ class PaymentDAO(private val db: Database) { OutgoingTxMetadata( date = it.getLong("execution_time").asInstant(), amount = it.getDecimal("amount"), - subject = it.getString("wire_transfer_subject"), - creditor = it.getString("credit_payto_uri"), - id = it.getString("message_id"), + subject = it.getString("subject"), + creditor = it.getString("credit_payto"), + id = it.getString("end_to_end_id"), wtid = it.getBytes("wtid")?.run { ShortHashCode(this) }, exchangeBaseUrl = it.getString("exchange_base_url") ) @@ -265,17 +268,18 @@ class PaymentDAO(private val db: Database) { suspend fun metadataInitiated(): List<InitiatedTxMetadata> = db.serializable( """ SELECT - (amount).val as amount_val + (amount).val as amount_val ,(amount).frac AS amount_frac - ,wire_transfer_subject + ,subject ,initiation_time - ,last_submission_time + ,submission_date ,submission_counter - ,credit_payto_uri - ,submitted - ,request_uid - ,failure_message + ,credit_payto + ,end_to_end_id + ,initiated_outgoing_transactions.status + ,initiated_outgoing_transactions.status_msg FROM initiated_outgoing_transactions + LEFT JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) ORDER BY initiation_time """ ) { @@ -283,12 +287,12 @@ class PaymentDAO(private val db: Database) { InitiatedTxMetadata( date = it.getLong("initiation_time").asInstant(), amount = it.getDecimal("amount"), - subject = it.getString("wire_transfer_subject"), - creditor = it.getString("credit_payto_uri"), - id = it.getString("request_uid"), - status = it.getString("submitted"), - msg = it.getString("failure_message"), - submissionTime = it.getLong("last_submission_time").asInstant(), + subject = it.getString("subject"), + creditor = it.getString("credit_payto"), + id = it.getString("end_to_end_id"), + status = it.getString("status"), + msg = it.getString("status_msg"), + submissionTime = it.getLong("submission_date").asInstant(), submissionCounter = it.getInt("submission_counter") ) } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsAdministrative.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsAdministrative.kt @@ -29,23 +29,33 @@ data class VersionNumber(val number: Float, val schema: String) { override fun toString(): String = "$number:$schema" } -data class HKD ( - val account: AccountInfo, - val orders: List<OrderInfo>, - val permissions: List<OrderInfo>, - val status: UserStatus +data class HKD( + val partner: PartnerInfo, + val users: List<UserInfo> ) -data class AccountInfo ( - val currency: String?, - val iban: String?, - val name: String? +data class PartnerInfo( + val name: String?, + val accounts: List<AccountInfo>, + val orders: List<OrderInfo> ) -data class OrderInfo ( - val type: String, - val params: String, +data class OrderInfo( + val order: EbicsOrder, val description: String, ) -// TODO use this in ebics setup to get current state and required actions +data class AccountInfo( + val currency: String, + val iban: String, +) +data class UserInfo( + val id: String, + val status: UserStatus, + val permissions: List<EbicsOrder>, +) + +data class HAA( + val orders: List<EbicsOrder> +) + enum class UserStatus(val description: String) { Ready("Subscriber is permitted access"), New("Subscriber is established, pending access permission"), @@ -71,7 +81,7 @@ object EbicsAdministrative { EbicsReturnCode.lookup(one("ReturnCode").text()) } val versions = map("VersionNumber") { - VersionNumber(text().toFloat(), attr("ProtocolVersion")) + VersionNumber(text().toFloat(), attr("ProtocolVersion")!!) } EbicsResponse( technicalCode = technicalCode, @@ -81,67 +91,75 @@ object EbicsAdministrative { } } - fun parseHKD(stream: InputStream): HKD { - fun XmlDestructor.orderInfo() = OrderInfo( - one("AdminOrderType").text(), - opt("Service") { - // TODO user a structured type to enable comparison - val params = StringBuilder() - opt("ServiceName")?.run { - params.append(" ${text()}") - } - opt("Scope")?.run { - params.append(" ${text()}") - } - opt("ServiceOption")?.run { - params.append(" ${text()}") - } - opt("MsgName")?.run { - params.append(" ${text()}") - } - opt("Container")?.run { - params.append(" ${attr("containerType")}") - } - params.toString() - } ?: "", - opt("Description")?.text() ?: "" + private fun XmlDestructor.ebicsOrder(type: String): EbicsOrder = + EbicsOrder.V3( + type = type, + service = opt("ServiceName")?.text(), + scope = opt("Scope")?.text(), + option = opt("ServiceOption")?.text(), + container = opt("Container")?.attr("containerType"), + message = opt("MsgName")?.text(), + version = opt("MsgName")?.optAttr("version"), ) - // TODO handle multiple partner, accounts and user using their respective ids + + fun parseHKD(stream: InputStream): HKD { + fun XmlDestructor.order(): EbicsOrder { + val type = one("AdminOrderType").text() + return opt("Service") { + ebicsOrder(type) + } ?: EbicsOrder.V3(type) + } return XmlDestructor.fromStream(stream, "HKDResponseOrderData") { - val (account, orders) = one("PartnerInfo") { - var currency: String? = null - var iban: String? = null - val name = opt("AddressInfo")?.one("Name")?.text() - opt("AccountInfo") { - currency = attr("Currency") + val partnerInfo = one("PartnerInfo") { + val name = one("AddressInfo").opt("Name")?.text() + val accounts = map("AccountInfo") { + var currency = attr("Currency") + lateinit var iban: String each("AccountNumber") { if (attr("international") == "true") { iban = text() } } + AccountInfo(currency, iban) + } + val orders = map("OrderInfo") { + OrderInfo( + order = order(), + description = one("Description").text() + ) } - val orders = map("OrderInfo") { orderInfo() } - Pair(AccountInfo(currency, iban, name), orders) + PartnerInfo(name, accounts, orders) } - val (permissions, status) = one("UserInfo") { - val userId = one("UserID").text() - val status = when (val status = one("UserID").attr("Status")) { - "1" -> UserStatus.Ready - "2" -> UserStatus.New - "3" -> UserStatus.INI - "4" -> UserStatus.HIA - "5" -> UserStatus.Initialised - "6" -> UserStatus.SuspendedFailedAttempts - // 7 is not applicable per spec - "8" -> UserStatus.SuspendedSPR - "9" -> UserStatus.SuspendedBank - else -> throw Exception("Unknown user statte $status") + val usersInfo = map("UserInfo") { + val (id, status) = one("UserID") { + val id = text() + val status = when (val status = attr("Status")) { + "1" -> UserStatus.Ready + "2" -> UserStatus.New + "3" -> UserStatus.INI + "4" -> UserStatus.HIA + "5" -> UserStatus.Initialised + "6" -> UserStatus.SuspendedFailedAttempts + // 7 is not applicable per spec + "8" -> UserStatus.SuspendedSPR + "9" -> UserStatus.SuspendedBank + else -> throw Exception("Unknown user statte $status") + } + Pair(id, status) } - val userName = opt("Name")?.text() - val permissions = map("Permission") { orderInfo() } - Pair(permissions, status) + val permissions = map("Permission") { order() } + UserInfo(id, status, permissions) + } + HKD(partnerInfo, usersInfo) + } + } + + fun parseHAA(stream: InputStream): HAA { + return XmlDestructor.fromStream(stream, "HAAResponseOrderData") { + val orders = map("Service") { + ebicsOrder("BTD") } - HKD(account, orders, permissions, status) + HAA(orders) } } } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt @@ -28,8 +28,8 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.withContext import org.w3c.dom.Document import org.xml.sax.SAXException -import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.* +import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.nexus.* import tech.libeufin.nexus.db.Database import java.io.InputStream @@ -80,7 +80,7 @@ suspend fun HttpClient.postToBank( throw EbicsError.HTTP("$phase: bank HTTP error: ${res.status}", res.status) } try { - val bodyStream = res.bodyAsChannel().toInputStream(); + val bodyStream = res.bodyAsChannel().toInputStream() val loggedStream = stepLogger?.log(msg, bodyStream) ?: bodyStream return XMLUtil.parseIntoDom(loggedStream) } catch (e: SAXException) { @@ -102,12 +102,12 @@ suspend fun EbicsBTS.postBTS( doc, bankKeys.bank_authentication_public_key )) { - throw EbicsError.Protocol("$phase: bank signature did not verify") + throw EbicsError.Protocol("$phase ${order.description()}: bank signature did not verify") } val response = try { EbicsBTS.parseResponse(doc) } catch (e: Exception) { - throw EbicsError.Protocol("$phase: invalid ebics response", e) + throw EbicsError.Protocol("$phase ${order.description()}: invalid ebics response", e) } logger.debug { buildString { @@ -148,7 +148,8 @@ class EbicsClient( endDate: Instant?, processing: suspend (InputStream) -> Unit, ) { - logger.debug { "Download order ${order.description()}" } + val description = order.description() + logger.debug { "Download order $description" } val txLog = ebicsLogger.tx(order) val impl = EbicsBTS(cfg, bankKeys, clientKeys, order) @@ -171,22 +172,22 @@ class EbicsClient( if (initResp.bankCode == EbicsReturnCode.EBICS_NO_DOWNLOAD_DATA_AVAILABLE) { return@withContext null } - val initContent = initResp.okOrFail("Download init") + val initContent = initResp.okOrFail("Download init $description") val tId = requireNotNull(initContent.transactionID) { - "Download init: missing transaction ID" + "Download init $description: missing transaction ID" } db.ebics.register(tId) Pair(tId, initContent) } val (tId, initContent) = if (init == null) return else init val howManySegments = requireNotNull(initContent.numSegments) { - "Download init: missing num segments" + "Download init $description: missing num segments" } val firstSegment = requireNotNull(initContent.segment) { - "Download init: missing OrderData" + "Download init $description: missing OrderData" } val dataEncryptionInfo = requireNotNull(initContent.dataEncryptionInfo) { - "Download init: missing EncryptionInfo" + "Download init $description: missing EncryptionInfo" } // Transfer phase @@ -194,13 +195,14 @@ class EbicsClient( for (x in 2 .. howManySegments) { val transReq = impl.downloadTransfer(x, howManySegments, tId) val transResp = impl.postBTS(client, transReq, "Download transfer", txLog.step("transfer$x")) - .okOrFail("Download transfer") + .okOrFail("Download transfer $description") val segment = requireNotNull(transResp.segment) { "Download transfer: missing encrypted segment" } segments.add(segment) } + // Decompress encrypted chunks val payloadStream = try { decryptAndDecompressPayload( @@ -226,7 +228,7 @@ class EbicsClient( // First send a proper EBICS transaction receipt val xml = impl.downloadReceipt(tId, res.isSuccess) impl.postBTS(client, xml, "Download receipt", txLog.step("receipt")) - .okOrFail("Download receipt") + .okOrFail("Download receipt $description") runCatching { db.ebics.remove(tId) } // Then throw business logic exception if any res.getOrThrow() @@ -243,7 +245,8 @@ class EbicsClient( order: EbicsOrder, payload: ByteArray, ): String { - logger.debug { "Upload order ${order.description()}" } + val description = order.description(); + logger.debug { "Upload order $description" } val txLog = ebicsLogger.tx(order) val impl = EbicsBTS(cfg, bankKeys, clientKeys, order) val preparedPayload = prepareUploadPayload(cfg, clientKeys, bankKeys, payload) @@ -251,12 +254,12 @@ class EbicsClient( // Init phase val initXml = impl.uploadInitialization(preparedPayload) val initResp = impl.postBTS(client, initXml, "Upload init", txLog.step("init")) - .okOrFail("Upload init") + .okOrFail("Upload init $description") val tId = requireNotNull(initResp.transactionID) { - "Upload init: missing transaction ID" + "Upload init $description: missing transaction ID" } val orderId = requireNotNull(initResp.orderID) { - "Upload init: missing order ID" + "Upload init $description: missing order ID" } txLog.payload(payload, "xml") @@ -264,8 +267,8 @@ class EbicsClient( // Transfer phase for (i in 1..preparedPayload.segments.size) { val transferXml = impl.uploadTransfer(tId, preparedPayload, i) - val transferResp = impl.postBTS(client, transferXml, "Upload transfer", txLog.step("transfer$i")) - .okOrFail("Upload transfer") + impl.postBTS(client, transferXml, "Upload transfer", txLog.step("transfer$i")) + .okOrFail("Upload transfer $description") } return orderId } @@ -375,6 +378,12 @@ fun getNonce(size: Int): ByteArray { return ByteArray(size / 8).rand(SECURE_RNG) } +private val EBICS_ID_ALPHABET = ('A'..'Z') + ('0'..'9') + +fun randEbicsId(): String { + return List(34) { EBICS_ID_ALPHABET.random() }.joinToString("") +} + class DataEncryptionInfo( val transactionKey: ByteArray, val bankPubDigest: ByteArray diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsOrder.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsOrder.kt @@ -33,39 +33,50 @@ sealed class EbicsOrder(val schema: String) { val version: String? = null, val container: String? = null, val option: String? = null - ): EbicsOrder("H005") - - companion object { - val WSS_PARAMS = EbicsOrder.V3( - type = "BTD", - service = "OTH", - scope = "DE", - message = "wssparam" - ) + ): EbicsOrder("H005") { + companion object { + val WSS_PARAMS = V3( + type = "BTD", + service = "OTH", + scope = "DE", + message = "wssparam" + ) + val HAC = V3(type = "HAC") + val HKD = V3(type = "HKD") + val HAA = V3(type = "HAA") + } } fun description(): String = buildString { when (this@EbicsOrder) { - is EbicsOrder.V2_5 -> { + is V2_5 -> { append(type) append('-') append(attribute) } - is EbicsOrder.V3 -> { + is V3 -> { append(type) - for (part in sequenceOf(service, message, option)) { + for (part in sequenceOf(service, scope, option, container)) { if (part != null) { append('-') append(part) } } + if (message != null) { + append('-') + append(message) + if (version != null) { + append('.') + append(version) + } + } } } } fun doc(): OrderDoc? { return when (this) { - is EbicsOrder.V2_5 -> { + is V2_5 -> { when (this.type) { "HAC" -> OrderDoc.acknowledgement "Z01" -> OrderDoc.status @@ -75,7 +86,7 @@ sealed class EbicsOrder(val schema: String) { else -> null } } - is EbicsOrder.V3 -> { + is V3 -> { when (this.type) { "HAC" -> OrderDoc.acknowledgement "BTD" -> when (this.message) { @@ -128,7 +139,6 @@ enum class Dialect { fun downloadDoc(doc: OrderDoc, ebics2: Boolean): EbicsOrder { return when (this) { postfinance -> { - // TODO test platform need EBICS2 for HAC, should we use a separate dialect ? if (ebics2) { when (doc) { OrderDoc.acknowledgement -> EbicsOrder.V2_5("HAC", "DZHNN") @@ -139,7 +149,7 @@ enum class Dialect { } } else { when (doc) { - OrderDoc.acknowledgement -> EbicsOrder.V3("HAC") + OrderDoc.acknowledgement -> EbicsOrder.V3.HAC OrderDoc.status -> EbicsOrder.V3("BTD", "PSR", "CH", "pain.002", "10", "ZIP") OrderDoc.report -> EbicsOrder.V3("BTD", "STM", "CH", "camt.052", "08", "ZIP") OrderDoc.statement -> EbicsOrder.V3("BTD", "EOP", "CH", "camt.053", "08", "ZIP") @@ -149,7 +159,7 @@ enum class Dialect { } // TODO for GLS we might have to fetch the same kind of files from multiple orders gls -> when (doc) { - OrderDoc.acknowledgement -> EbicsOrder.V3("HAC") + OrderDoc.acknowledgement -> EbicsOrder.V3.HAC OrderDoc.status -> EbicsOrder.V3("BTD", "REP", "DE", "pain.002", null, "ZIP", "SCT") OrderDoc.report -> EbicsOrder.V3("BTD", "STM", "DE", "camt.052", null, "ZIP") OrderDoc.statement -> EbicsOrder.V3("BTD", "EOP", "DE", "camt.053", null, "ZIP") @@ -164,4 +174,12 @@ enum class Dialect { gls -> EbicsOrder.V3("BTU", "SCT", null, "pain.001") } } + + /** All orders required for a dialect implementation to work */ + fun orders(): Set<EbicsOrder> = ( + // Administrative orders + sequenceOf(EbicsOrder.V3.HAA, EbicsOrder.V3.HKD) + // and documents orders + + OrderDoc.entries.map { downloadDoc(it, false) } + ).toSet() } \ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsWS.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsWS.kt @@ -25,10 +25,10 @@ import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.kotlinx.* import io.ktor.websocket.* +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.* -import kotlinx.coroutines.channels.* -import kotlinx.coroutines.* import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.common.* @@ -98,14 +98,14 @@ sealed interface WssNotification { /** Download EBICS real-time notifications websocket params */ suspend fun EbicsClient.wssParams(): WssParams { lateinit var params: WssParams - download(EbicsOrder.WSS_PARAMS, null, null) { stream -> + download(EbicsOrder.V3.WSS_PARAMS, null, null) { stream -> params = Json.decodeFromStream(stream) } return params } /** Receive a JSON message from a websocket session */ -inline suspend fun <reified T> DefaultClientWebSocketSession.receiveJson(): T { +private suspend inline fun <reified T> DefaultClientWebSocketSession.receiveJson(): T { val frame = incoming.receive() val content = frame.readBytes() val msg = Json.decodeFromStream(kotlinx.serialization.serializer<T>(), content.inputStream()) @@ -142,11 +142,6 @@ suspend fun WssParams.connect(client: HttpClient, lambda: suspend (WssNotificati // TODO use receiveDeserialized from ktor when it works val msg = receiveJson<WssNotification>() logger.trace("received: {}", msg) - if (msg is WssGeneralInfo) { - for (info in msg.INFO) { - logger.info("info: {}", info.FREE) - } - } lambda(msg) } } @@ -154,7 +149,7 @@ suspend fun WssParams.connect(client: HttpClient, lambda: suspend (WssNotificati suspend fun listenForNotification(client: EbicsClient): ReceiveChannel<List<EbicsOrder>>? { // Try to get params - val params = try { + try { client.wssParams() } catch (e: EbicsError) { if ( @@ -181,19 +176,26 @@ suspend fun listenForNotification(client: EbicsClient): ReceiveChannel<List<Ebic logger.trace("{}", params) params.connect(client.client) { msg -> backoff.reset() - if (msg is WssNewData) { - val orders = msg.BTF.map { - EbicsOrder.V3( - type = "BTD", - service = it.SERVICE, - scope = it.SCOPE, - message = it.MSGNAME, - version = it.VERSION, - container = it.CONTTYPE, - option = it.OPTION - ) + when (msg) { + is WssGeneralInfo -> { + for (info in msg.INFO) { + logger.info("info: {}", info.FREE) + } + } + is WssNewData -> { + val orders = msg.BTF.map { + EbicsOrder.V3( + type = "BTD", + service = it.SERVICE, + scope = it.SCOPE, + message = it.MSGNAME, + version = it.VERSION, + container = it.CONTTYPE, + option = it.OPTION + ) + } + channel.send(orders) } - channel.send(orders) } } } catch (e: Exception) { diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt @@ -0,0 +1,386 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ + +// THIS FILE IS GENERATED, DO NOT EDIT + +package tech.libeufin.nexus.iso20022 + +enum class ExternalBankTransactionDomainCode(val description: String) { + ACMT("Account Management"), + CAMT("Cash Management"), + CMDT("Commodities"), + DERV("Derivatives"), + FORX("Foreign Exchange"), + LDAS("Loans, Deposits & Syndications"), + PMET("Precious Metal"), + PMNT("Payments"), + SECU("Securities"), + TRAD("Trade Services"), + XTND("Extended Domain"), +} + +enum class ExternalBankTransactionFamilyCode(val description: String) { + ACCB("Account Balancing"), + ACOP("Additional Miscellaneous Credit Operations"), + ADOP("Additional Miscellaneous Debit Operations"), + BLOC("Blocked Transactions"), + CAPL("Cash Pooling"), + CASH("Miscellaneous Securities Operations"), + CCRD("Customer Card Transactions"), + CLNC("Clean Collection"), + CNTR("Counter Transactions"), + COLC("Custody Collection"), + COLL("Collateral Management"), + CORP("Corporate Action"), + CSLN("Consumer Loans"), + CUST("Custody"), + DCCT("Documentary Credit"), + DLVR("Delivery"), + DOCC("Documentary Collection"), + DRFT("Drafts"), + FTDP("Fixed Term Deposits"), + FTLN("Fixed Term Loans"), + FTUR("Futures"), + FWRD("Forwards"), + GUAR("Guarantees"), + ICCN("Issued Cash Concentration Transactions"), + ICDT("Issued Credit Transfers"), + ICHQ("Issued Cheques"), + IDDT("Issued Direct Debits"), + IRCT("Issued Real-Time Credit Transfers"), + LACK("Lack"), + LBOX("Lockbox Transactions"), + LFUT("Listed Derivatives - Futures"), + LOCT("Stand-By Letter Of Credit"), + LOPT("Listed Derivatives - Options"), + MCOP("Miscellaneous Credit Operations"), + MCRD("Merchant Card Transactions"), + MDOP("Miscellaneous Debit Operations"), + MGLN("Mortgage Loans"), + NDFX("Non Deliverable"), + NSET("Non Settled"), + NTAV("Not Available"), + NTDP("Notice Deposits"), + NTLN("Notice Loans"), + OBND("OTC Derivatives - Bonds"), + OCRD("OTC Derivatives - Credit"), + OEQT("OTC Derivatives - Equity"), + OIRT("OTC Derivatives - Interest Rates"), + OPCL("Opening & Closing"), + OPTN("Options"), + OSED("OTC Derivatives - Structured Exotic Derivatives"), + OSWP("OTC Derivatives – Swaps"), + OTHB("CSD Blocked transactions"), + OTHR("Other"), + RCCN("Received Cash Concentration Transactions"), + RCDT("Received Credit Transfers"), + RCHQ("Received Cheques"), + RDDT("Received Direct Debits"), + RRCT("Received Real-Time Credit Transfers"), + SETT("Trade, Clearing and Settlement"), + SPOT("Spots"), + SWAP("Swaps"), + SYDN("Syndications"), +} + +enum class ExternalBankTransactionSubFamilyCode(val description: String) { + ACCC("Account Closing"), + ACCO("Account Opening"), + ACCT("Account Transfer"), + ACDT("ACH Credit"), + ACOR("ACH Corporate Trade"), + ADBT("ACH Debit"), + ADJT("Adjustments (Generic)"), + APAC("ACH Pre-Authorised"), + ARET("ACH Return"), + AREV("ACH Reversal"), + ARPD("ARP Debit"), + ASET("ACH Settlement"), + ATXN("ACH Transaction"), + AUTT("Automatic Transfer"), + BBDD("SEPA B2B Direct Debit"), + BCDP("Branch Deposit"), + BCHQ("Bank Cheque"), + BCKV("Back Value"), + BCWD("Branch Withdrawl"), + BFWD("Bond Forward"), + BIDS("Repurchase Offer/Issuer Bid/Reverse Rights."), + BKFE("Bank Fees"), + BONU("Bonus Issue/Capitalisation Issue"), + BOOK("Internal Book Transfer"), + BPUT("Put Redemption"), + BROK("Brokerage Fee"), + BSBC("Sell Buy Back"), + BSBO("Buy Sell Back"), + CAJT("Credit Adjustments (Generic)"), + CAPG("Capital Gains Distribution"), + CASH("Cash Letter"), + CCCH("Certified Customer Cheque"), + CCHQ("Cheque"), + CCIR("Cross Currency IRS"), + CCPC("CCP Cleared Initial Margin"), + CCPM("CCP Cleared Variation Margin"), + CCSM("CCP Cleared Segregated Initial Margin"), + CDIS("Controlled Disbursement"), + CDPT("Cash Deposit"), + CHAR("Charge/Fees"), + CHKD("Check Deposit"), + CHRG("Charges (Generic)"), + CLAI("Compensation/Claims"), + CLCQ("Circular Cheque"), + CMBO("Corporate Mark Broker Owned"), + CMCO("Corporate Mark Client Owned"), + COME("Commission Excluding Taxes (Generic)"), + COMI("Commission Including Taxes (Generic)"), + COMM("Commission (Generic)"), + COMT("Non Taxable Commissions (Generic)"), + CONV("Conversion"), + COVE("Cover Transaction"), + CPEN("Cash Penalties"), + CPRB("Corporate Rebate"), + CQRV("Cheque Reversal"), + CRCQ("Crossed Cheque"), + CRDS("Credit DefaultSwap"), + CROS("Cross Trade"), + CRPR("Cross Product"), + CRSP("Credit Support"), + CRTL("Credit Line"), + CSHA("Cash Letter Adjustment"), + CSLI("Cash In Lieu"), + CWDL("Cash Withdrawal"), + DAJT("Debit Adjustments (Generic)"), + DDFT("Discounted Draft"), + DDWN("Drawdown"), + DECR("Decrease in Value"), + DMCG("Draft Maturity Change"), + DMCT("Domestic Credit Transfer"), + DPST("Deposit"), + DRAW("Drawing"), + DRIP("Dividend Reinvestment"), + DSBR("Controlled Disbursement"), + DTCH("Dutch Auction"), + DVCA("Cash Dividend"), + DVOP("Dividend Option"), + ENCT("Nordic Payment Council Credit Transfer"), + EQBO("Equity Mark Broker Owned"), + EQCO("Equity Mark Client Owned"), + EQPT("Equity Option"), + EQUS("Equity Swap"), + ERTA("Exchange Rate Adjustment"), + ERWA("Lending Income"), + ERWI("Borrowing Fee"), + ESCT("SEPA Credit Transfer"), + ESDD("SEPA Core Direct Debit"), + EXOF("Exchange"), + EXPT("Exotic Option"), + EXRI("Call On Intermediate Securities"), + EXTD("Exchange Traded Derivatives"), + EXWA("Warrant Exercise/Warrant Conversion"), + FCDP("Foreign Currencies Deposit"), + FCTA("Factor Update"), + FCWD("Foreign Currencies Withdrawal"), + FEES("Fees (Generic)"), + FICT("Financial Institution Credit Transfer"), + FIDD("Financial Institution Direct Debit Payment"), + FIOA("Financial Institution Own Account Transfer"), + FIXI("Fixed Income"), + FLTA("Float Adjustment"), + FRZF("Freeze Of Funds"), + FUCO("Futures Commission"), + FUTU("Future Variation Margin"), + FWBC("Forwards Broker Owned Collateral"), + FWCC("Forwards Client Owned Collateral"), + FWSB("MFA Segregated Broker Cash Collateral"), + FWSC("MFA Segregated Client Cash Collateral"), + GEN1("Withdrawal/Distribution"), + GEN2("Deposit/Contribution"), + IADD("Invoice Accepted with Differed Due Date"), + INFD("Fixed Deposit Interest Amount"), + INSP("Inspeci/Share Exchange"), + INTR("Interest Payment"), + ISSU("Depositary Receipt Issue"), + LBCA("Credit Adjustment"), + LBDP("Deposit"), + LIQU("Liquidation Dividend / Liquidation Payment"), + MARG("Margin Payments"), + MBSB("Mortgage Back Segregated Broker Cash Collateral"), + MBSC("Mortgage Back Segregated Client Cash Collateral"), + MCAL("Full Call / Early Redemption"), + MGCC("Margin Client Owned Cash Collateral"), + MGSC("Initial Futures Margin Segregated Client Cash Collateral"), + MIXD("Mixed Deposit"), + MNFE("Management Fees"), + MRGR("Merger"), + MSCD("Miscellaneous Deposit"), + NETT("Netting"), + NPCC("Non Presented Circular Cheques"), + NSYN("Non Syndicated"), + NTAV("Not Available"), + NWID("New issue distribution"), + OCCC("Client owned OCC pledged collateral"), + ODFT("Overdraft"), + ODLT("Odd Lot Sale/Purchase"), + OODD("One-Off Direct Debit"), + OPBC("Option Broker Owned Collateral"), + OPCC("Option Client Owned Collateral"), + OPCQ("Open Cheque"), + OPSB("OTC Option Segregated Broker Cash Collateral"), + OPSC("OTC Option Segregated Client Cash Collateral"), + OPTN("FX Option"), + ORCQ("Order Cheque"), + OTCC("OTC CCP"), + OTCD("OTC Derivatives"), + OTCG("OTC"), + OTCN("OTC Non-CCP"), + OTHR("Other"), + OVCH("Overdraft Charge"), + OWNE("External Account Transfer"), + OWNI("Internal Account Transfer"), + PADD("Pre-Authorised Direct Debit"), + PAIR("Pair-Off"), + PCAL("Partial Redemption With Reduction Of Nominal Value"), + PLAC("Placement"), + PMDD("Direct Debit"), + PORT("Portfolio Move"), + POSC("Credit Card Payment"), + POSD("Point-of-Sale (POS) Payment - Debit Card"), + PPAY("Principal Payment"), + PRCT("Priority Credit Transfer"), + PRDD("Reversal Due To Payment Reversal"), + PRED("Partial Redemption Without Reduction Of Nominal Value"), + PRII("Interest Payment with Principles"), + PRIN("Interest Payment with Principles"), + PRIO("Priority Issue"), + PRUD("Principal Pay-Down/Pay-Up"), + PSTE("Posting Error"), + RCDD("Reversal Due To Payment Cancellation Request"), + RCOV("Reversal due to a Cover Transaction Return"), + REAA("Redemption Asset Allocation"), + REDM("Final Maturity"), + REPU("Repo"), + RESI("Futures Residual Amount"), + RHTS("Rights Issue/Subscription Rights/Rights Offer"), + RIMB("Reimbursement (Generic)"), + RNEW("Renewal"), + RPBC("Bi-lateral repo broker owned collateral"), + RPCC("Repo client owned collateral"), + RPCR("Reversal Due To Payment Cancellation Request"), + RPMT("Repayment"), + RPSB("Bi-lateral Repo Segregated Broker Cash Collateral"), + RPSC("Bi-lateral Repo Segregated Client Cash Collateral"), + RRTN("Reversal Due To Payment Return"), + RVPO("Reverse Repo"), + RWPL("Redemption Withdrawing Plan"), + SABG("Settlement Against Bank Guarantee"), + SALA("Payroll/Salary Payment"), + SBSC("Securities Buy Sell Sell Buy Back"), + SCIE("Single Currency IRS Exotic"), + SCIR("Single Currency IRS"), + SCRP("Securities Cross Products"), + SDVA("Same Day Value Credit Transfer"), + SECB("Securities Borrowing"), + SECL("Securities Lending"), + SHBC("Broker owned collateral Short Sale"), + SHCC("Client owned collateral Short Sale"), + SHPR("Equity Premium Reserve"), + SHSL("Short Sell"), + SLBC("Lending Broker Owned Cash Collateral"), + SLCC("Lending Client Owned Cash Collateral"), + SLEB("Securities Lending And Borrowing"), + SLOA("SecuredLoan"), + SOSE("Settlement Of Sight Export Document"), + SOSI("Settlement Of Sight Import Document"), + SSPL("Subscription Savings Plan"), + STAC("Settlement After Collection"), + STAM("Settlement At Maturity"), + STDO("Standing Order"), + STLM("Settlement"), + STLR("Settlement Under Reserve"), + STOD("Bill of Exchange Settlement on Demand"), + SUAA("Subscription Asset Allocation"), + SUBS("Subscription"), + SWAP("Swap Payment"), + SWBC("Swap Broker Owned Collateral"), + SWCC("Client Owned Collateral"), + SWEP("Sweep"), + SWFP("Final Payment"), + SWIC("Switch"), + SWPP("Partial Payment"), + SWPT("Swaption"), + SWRS("Reset Payment"), + SWSB("ISDA/CSA Segregated Broker Cash Collateral"), + SWSC("ISDA/CSA Segregated Client Cash Collateral"), + SWUF("Upfront Payment"), + SYND("Syndicated"), + TAXE("Taxes (Generic)"), + TBAC("TBA Closing"), + TBAS("To Be Announced"), + TBBC("TBA Broker owned cash collateral"), + TBCC("TBA Client owned cash collateral"), + TCDP("Travellers Cheques Deposit"), + TCWD("Travellers Cheques Withdrawal"), + TEND("Tender"), + TOPG("Topping"), + TOUT("Transfer Out"), + TRAD("Trade"), + TRCP("Treasury Cross Product"), + TREC("Tax Reclaim"), + TRFE("Transaction Fees"), + TRIN("Transfer In"), + TRPO("Triparty Repo"), + TRVO("Triparty Reverse Repo"), + TTLS("Treasury Tax And Loan Service"), + TURN("Turnaround"), + UDFT("Dishonoured/Unpaid Draft"), + UNCO("Underwriting Commission"), + UPCQ("Unpaid Cheque"), + UPCT("Unpaid Card Transaction"), + UPDD("Reversal Due To Return/Unpaid Direct Debit"), + URCQ("Cheque Under Reserve"), + URDD("Direct Debit Under Reserve"), + VALD("Value Date"), + VCOM("Credit Transfer With Agreed Commercial Information"), + WITH("Withholding Tax"), + XBCP("Cross-Border Credit Card Payment"), + XBCQ("Foreign Cheque"), + XBCT("Cross-Border Credit Transfer"), + XBCW("Cross-Border Cash Withdrawal"), + XBRD("Cross-Border"), + XBSA("Cross-Border Payroll/Salary Payment"), + XBST("Cross-Border Standing Order"), + XCHC("Exchange Traded CCP"), + XCHG("Exchange Traded"), + XCHN("Exchange Traded Non-CCP"), + XICT("Cross-Border Intra Company Transfer"), + XPCQ("Unpaid Foreign Cheque"), + XRCQ("Foreign Cheque Under Reserve"), + XRTN("Cross Border Reversal Due to Payment Return"), + YTDA("YTD Adjustment"), + ZABA("Zero Balancing"), + ACON("ACH Concentration"), + BACT("Branch Account Transfer"), + COAT("Corporate Own Account Transfer"), + ICCT("Intra Company Transfer"), + LBDB("Debit"), + POSP("Point-of-Sale (POS) Payment"), + SMCD("Smart-Card Payment"), + SMRT("Smart-Card Payment"), + XBDD("Cross-Border Direct Debit"), +} + diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Constants.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Constants.kt @@ -0,0 +1,37 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ + +package tech.libeufin.nexus.iso20022 + +enum class HacAction(val description: String) { + FILE_UPLOAD("File submitted to the bank"), + FILE_DOWNLOAD("File downloaded from the bank"), + ES_UPLOAD("Electronic signature submitted to the bank"), + ES_DOWNLOAD("Electronic signature downloaded from the bank"), + ES_VERIFICATION("Signature verification"), + VEU_FORWARDING("Forwarding to EDS"), + VEU_VERIFICATION("EDS signature verification"), + VEU_VERIFICATION_END("VEU_VERIFICATION_END"), + VEU_CANCEL_ORDER("Cancellation of EDS order"), + ADDITIONAL("Additional information"), + ORDER_HAC_FINAL_POS("HAC end of order (positive)"), + ORDER_HAC_FINAL_NEG("HAC end of order (negative)"), + // Not in the spec but Credit Suisse test suite use it + ORDER_HAC_FINAL("HAC end of order") +} +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt @@ -0,0 +1,459 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ + +// THIS FILE IS GENERATED, DO NOT EDIT + +package tech.libeufin.nexus.iso20022 + +enum class ExternalStatusReasonCode(val isoCode: String, val description: String) { + AB01("AbortedClearingTimeout", "Clearing process aborted due to timeout."), + AB02("AbortedClearingFatalError", "Clearing process aborted due to a fatal error."), + AB03("AbortedSettlementTimeout", "Settlement aborted due to timeout."), + AB04("AbortedSettlementFatalError", "Settlement process aborted due to a fatal error."), + AB05("TimeoutCreditorAgent", "Transaction stopped due to timeout at the Creditor Agent."), + AB06("TimeoutInstructedAgent", "Transaction stopped due to timeout at the Instructed Agent."), + AB07("OfflineAgent", "Agent of message is not online."), + AB08("OfflineCreditorAgent", "Creditor Agent is not online."), + AB09("ErrorCreditorAgent", "Transaction stopped due to error at the Creditor Agent."), + AB10("ErrorInstructedAgent", "Transaction stopped due to error at the Instructed Agent."), + AB11("TimeoutDebtorAgent", "Transaction stopped due to timeout at the Debtor Agent."), + AB12("InvalidConcurrentBatch", "Duplicate Concurrent Batch Sequence number– for Settlement Instructions."), + AB13("InvalidRoutingCodeUtilised", "Wrong Message Routing Type for Return-of-Funds."), + AB15("InvalidAccountNumberForSettlementType", "Instruction may not be placed on the Continuous Processing Line settlement processor."), + AB21("InvalidSettlementAgreementNumberSpecified", "Agreement number not valid (beneficiary)."), + AB26("InvalidBatchSettlementInstruction", "Settlement Instruction does not exist."), + AC01("IncorrectAccountNumber", "Account number is invalid or missing."), + AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing"), + AC03("InvalidCreditorAccountNumber", "Creditor account number invalid or missing"), + AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books."), + AC05("ClosedDebtorAccountNumber", "Debtor account number closed"), + AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), + AC07("ClosedCreditorAccountNumber", "Creditor account number closed"), + AC08("InvalidBranchCode", "Branch code is invalid or missing"), + AC09("InvalidAccountCurrency", "Account currency is invalid or missing"), + AC10("InvalidDebtorAccountCurrency", "Debtor account currency is invalid or missing"), + AC11("InvalidCreditorAccountCurrency", "Creditor account currency is invalid or missing"), + AC12("InvalidAccountType", "Account type missing or invalid."), + AC13("InvalidDebtorAccountType", "Debtor account type missing or invalid"), + AC14("InvalidCreditorAccountType", "Creditor account type missing or invalid"), + AC15("AccountDetailsChanged", "The account details for the counterparty have changed."), + AC16("CardNumberInvalid", "Credit or debit card number is invalid."), + AEXR("AlreadyExpiredRTP", "Request-to-pay Expiry Date and Time has already passed."), + AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), + AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), + AG03("TransactionNotSupported", "Transaction type not supported/authorized on this account"), + AG04("InvalidAgentCountry", "Agent country code is missing or invalid."), + AG05("InvalidDebtorAgentCountry", "Debtor agent country code is missing or invalid"), + AG06("InvalidCreditorAgentCountry", "Creditor agent country code is missing or invalid"), + AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), + AG08("InvalidAccessRights", "Transaction failed due to invalid or missing user or access right"), + AG09("PaymentNotReceived", "Original payment never received."), + AG10("AgentSuspended", "Agent of message is suspended from the Real Time Payment system."), + AG11("CreditorAgentSuspended", "Creditor Agent of message is suspended from the Real Time Payment system."), + AG12("NotAllowedBookTransfer", "Payment orders made by transferring funds from one account to another at the same financial institution (bank or payment institution) are not allowed."), + AG13("ForbiddenReturnPayment", "Returned payments derived from previously returned transactions are not allowed."), + AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect"), + ALAC("AlreadyAcceptedRTP", "Request-to-pay has already been accepted by the Debtor."), + AM01("ZeroAmount", "Specified message amount is equal to zero"), + AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), + AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), + AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), + AM05("Duplication", "Duplication"), + AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), + AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), + AM09("WrongAmount", "Amount received is not the amount agreed or expected"), + AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), + AM11("InvalidTransactionCurrency", "Transaction currency is invalid or missing"), + AM12("InvalidAmount", "Amount is invalid or missing"), + AM13("AmountExceedsClearingSystemLimit", "Transaction amount exceeds limits set by clearing system"), + AM14("AmountExceedsAgreedLimit", "Transaction amount exceeds limits agreed between bank and client"), + AM15("AmountBelowClearingSystemMinimum", "Transaction amount below minimum set by clearing system"), + AM16("InvalidGroupControlSum", "Control Sum at the Group level is invalid"), + AM17("InvalidPaymentInfoControlSum", "Control Sum at the Payment Information level is invalid"), + AM18("InvalidNumberOfTransactions", "Number of transactions is invalid or missing."), + AM19("InvalidGroupNumberOfTransactions", "Number of transactions at the Group level is invalid or missing"), + AM20("InvalidPaymentInfoNumberOfTransactions", "Number of transactions at the Payment Information level is invalid"), + AM21("LimitExceeded", "Transaction amount exceeds limits agreed between bank and client."), + AM22("ZeroAmountNotApplied", "Unable to apply zero amount to designated account. For example, where the rules of a service allow the use of zero amount payments, however the back-office system is unable to apply the funds to the account. If the rules of a service prohibit the use of zero amount payments, then code AM01 is used to report the error condition."), + AM23("AmountExceedsSettlementLimit", "Transaction amount exceeds settlement limit."), + AMSE("AttachmentMaximumSize", "Size of the attachment exceeds the allowed maximum."), + APAR("AlreadyPaidRTP", "Request To Pay has already been paid by the Debtor."), + ARFR("AlreadyRefusedRTP", "Request-to-pay has already been refused by the Debtor."), + ARJR("AlreadyRejectedRTP", "Request-to-pay has already been rejected."), + ATNS("AttachementsNotSupported", "Attachments to the request-to-pay are not supported."), + BDAY("NotBusinessDay", "Settlement Cycle Day and Calendar day should be the same."), + BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number. (formerly CreditorConsistency)."), + BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), + BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), + BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), + BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), + BE08("MissingDebtorName", "Debtor name is missing"), + BE09("InvalidCountry", "Country code is missing or Invalid."), + BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid"), + BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid"), + BE12("InvalidCountryOfResidence", "Country code of residence is missing or Invalid."), + BE13("InvalidDebtorCountryOfResidence", "Country code of debtor's residence is missing or Invalid"), + BE14("InvalidCreditorCountryOfResidence", "Country code of creditor's residence is missing or Invalid"), + BE15("InvalidIdentificationCode", "Identification code missing or invalid."), + BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid"), + BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid"), + BE18("InvalidContactDetails", "Contact details missing or invalid"), + BE19("InvalidChargeBearerCode", "Charge bearer code for transaction type is invalid"), + BE20("InvalidNameLength", "Name length exceeds local rules for payment type."), + BE21("MissingName", "Name missing or invalid. Generic usage if cannot specifically identify debtor or creditor."), + BE22("MissingCreditorName", "Creditor name is missing"), + BE23("AccountProxyInvalid", "Phone number or email address, or any other proxy, used as the account proxy is unknown or invalid."), + CERI("CheckERI", "Credit transfer is not tagged as an Extended Remittance Information (ERI) transaction but contains ERI."), + CH03("RequestedExecutionDateOrRequestedCollectionDateTooFarInFuture", "Value in Requested Execution Date or Requested Collection Date is too far in the future"), + CH04("RequestedExecutionDateOrRequestedCollectionDateTooFarInPast", "Value in Requested Execution Date or Requested Collection Date is too far in the past"), + CH07("ElementIsNotToBeUsedAtB-andC-Level", "Element is not to be used at B- and C-Level"), + CH09("MandateChangesNotAllowed", "Mandate changes are not allowed"), + CH10("InformationOnMandateChangesMissing", "Information on mandate changes are missing"), + CH11("CreditorIdentifierIncorrect", "Value in Creditor Identifier is incorrect"), + CH12("CreditorIdentifierNotUnambiguouslyAtTransaction-Level", "Creditor Identifier is ambiguous at Transaction Level"), + CH13("OriginalDebtorAccountIsNotToBeUsed", "Original Debtor Account is not to be used"), + CH14("OriginalDebtorAgentIsNotToBeUsed", "Original Debtor Agent is not to be used"), + CH15("ElementContentIncludesMoreThan140Characters", "Content Remittance Information/Structured includes more than 140 characters"), + CH16("ElementContentFormallyIncorrect", "Content is incorrect"), + CH17("ElementNotAdmitted", "Element is not allowed"), + CH19("ValuesWillBeSetToNextTARGETday", "Values in Interbank Settlement Date or Requested Collection Date will be set to the next TARGET day"), + CH20("DecimalPointsNotCompatibleWithCurrency", "Number of decimal points not compatible with the currency"), + CH21("RequiredCompulsoryElementMissing", "Mandatory element is missing"), + CH22("COREandB2BwithinOnemessage", "SDD CORE and B2B not permitted within one message"), + CHQC("ChequeSettledOnCreditorAccount", "Cheque has been presented in cheque clearing and settled on the creditor’s account."), + CN01("AuthorisationCancelled", "Authorisation is cancelled."), + CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), + CURR("IncorrectCurrency", "Currency of the payment is incorrect"), + CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), + DC02("SettlementNotReceived", "Rejection of a payment due to covering FI settlement not being received."), + DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), + DS01("ElectronicSignaturesCorrect", "The electronic signature(s) is/are correct"), + DS02("OrderCancelled", "An authorized user has cancelled the order"), + DS03("OrderNotCancelled", "The user’s attempt to cancel the order was not successful"), + DS04("OrderRejected", "The order was rejected by the bank side (for reasons concerning content)"), + DS05("OrderForwardedForPostprocessing", "The order was correct and could be forwarded for postprocessing"), + DS06("TransferOrder", "The order was transferred to VEU"), + DS07("ProcessingOK", "All actions concerning the order could be done by the EBICS bank server"), + DS08("DecompressionError", "The decompression of the file was not successful"), + DS09("DecryptionError", "The decryption of the file was not successful"), + DS0A("DataSignRequested", "Data signature is required."), + DS0B("UnknownDataSignFormat", "Data signature for the format is not available or invalid."), + DS0C("SignerCertificateRevoked", "The signer certificate is revoked."), + DS0D("SignerCertificateNotValid", "The signer certificate is not valid (revoked or not active)."), + DS0E("IncorrectSignerCertificate", "The signer certificate is not present."), + DS0F("SignerCertificationAuthoritySignerNotValid", "The authority of the signer certification sending the certificate is unknown."), + DS0G("NotAllowedPayment", "Signer is not allowed to sign this operation type."), + DS0H("NotAllowedAccount", "Signer is not allowed to sign for this account."), + DS0K("NotAllowedNumberOfTransaction", "The number of transaction is over the number allowed for this signer."), + DS10("Signer1CertificateRevoked", "The certificate is revoked for the first signer."), + DS11("Signer1CertificateNotValid", "The certificate is not valid (revoked or not active) for the first signer."), + DS12("IncorrectSigner1Certificate", "The certificate is not present for the first signer."), + DS13("SignerCertificationAuthoritySigner1NotValid", "The authority of signer certification sending the certificate is unknown for the first signer."), + DS14("UserDoesNotExist", "The user is unknown on the server"), + DS15("IdenticalSignatureFound", "The same signature has already been sent to the bank"), + DS16("PublicKeyVersionIncorrect", "The public key version is not correct. This code is returned when a customer sends signature files to the financial institution after conversion from an older program version (old ES format) to a new program version (new ES format) without having carried out re-initialisation with regard to a public key change."), + DS17("DifferentOrderDataInSignatures", "Order data and signatures don’t match"), + DS18("RepeatOrder", "File cannot be tested, the complete order has to be repeated. This code is returned in the event of a malfunction during the signature check, e.g. not enough storage space."), + DS19("ElectronicSignatureRightsInsufficient", "The user’s rights (concerning his signature) are insufficient to execute the order"), + DS20("Signer2CertificateRevoked", "The certificate is revoked for the second signer."), + DS21("Signer2CertificateNotValid", "The certificate is not valid (revoked or not active) for the second signer."), + DS22("IncorrectSigner2Certificate", "The certificate is not present for the second signer."), + DS23("SignerCertificationAuthoritySigner2NotValid", "The authority of signer certification sending the certificate is unknown for the second signer."), + DS24("WaitingTimeExpired", "Waiting time expired due to incomplete order"), + DS25("OrderFileDeleted", "The order file was deleted by the bank server"), + DS26("UserSignedMultipleTimes", "The same user has signed multiple times"), + DS27("UserNotYetActivated", "The user is not yet activated (technically)"), + DS28("ReturnForTechnicalReason", "Message routed to the wrong environment."), + DT01("InvalidDate", "Invalid date (eg, wrong or missing settlement date)"), + DT02("InvalidCreationDate", "Invalid creation date and time in Group Header (eg, historic date)"), + DT03("InvalidNonProcessingDate", "Invalid non bank processing date (eg, weekend or local public holiday)"), + DT04("FutureDateNotSupported", "Future date not supported"), + DT05("InvalidCutOffDate", "Associated message, payment information block or transaction was received after agreed processing cut-off date, i.e., date in the past."), + DT06("ExecutionDateChanged", "Execution Date has been modified in order for transaction to be processed"), + DU01("DuplicateMessageID", "Message Identification is not unique."), + DU02("DuplicatePaymentInformationID", "Payment Information Block is not unique."), + DU03("DuplicateTransaction", "Transaction is not unique."), + DU04("DuplicateEndToEndID", "End To End ID is not unique."), + DU05("DuplicateInstructionID", "Instruction ID is not unique."), + DUPL("DuplicatePayment", "Payment is a duplicate of another payment"), + ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), + ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), + ED05("SettlementFailed", "Settlement of the transaction has failed."), + ED06("SettlementSystemNotAvailable", "Interbank settlement system not available."), + EDNA("ExecutionDateNotAccepted", "Requested execution date of the payment is not accepted."), + EDTL("ExpiryDateTooLong", "Expiry date time of the request-to-pay is too far in the future."), + EDTR("ExpiryDateTimeReached", "Expiry date time of the request-to-pay is already reached."), + ERIN("ERIOptionNotSupported", "Extended Remittance Information (ERI) option is not supported."), + FF01("InvalidFileFormat", "File Format incomplete or invalid"), + FF02("SyntaxError", "Syntax error reason is provided as narrative information in the additional reason information."), + FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), + FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid"), + FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), + FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid"), + FF07("InvalidPurpose", "Purpose is missing or invalid"), + FF08("InvalidEndToEndId", "End to End Id missing or invalid"), + FF09("InvalidChequeNumber", "Cheque number missing or invalid"), + FF10("BankSystemProcessingError", "File or transaction cannot be processed due to technical issues at the bank side"), + FF11("ClearingRequestAborted", "Clearing request rejected due it being subject to an abort operation."), + FF12("OriginalTransactionNotEligibleForRequestedReturn", "Original payment is not eligible to be returned given its current status."), + FF13("RequestForCancellationNotFound", "No record of request for cancellation found."), + FOCR("FollowingCancellationRequest", "Return following a cancellation request."), + FR01("Fraud", "Returned as a result of fraud."), + FRAD("FraudulentOrigin", "Cancellation requested following a transaction that was originated fraudulently. The use of the FraudulentOrigin code should be governed by jurisdictions."), + G000("PaymentTransferredAndTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is tracked. No further updates will follow from the Status Originator."), + G001("PaymentTransferredAndNotTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is not tracked. No further updates will follow from the Status Originator."), + G002("CreditDebitNotConfirmed", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account may not be confirmed same day. Update will follow from the Status Originator."), + G003("CreditPendingDocuments", "In a FIToFI Customer Credit Transfer: Credit to creditor’s account is pending receipt of required documents. The Status Originator has requested creditor to provide additional documentation. Update will follow from the Status Originator."), + G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), + G005("DeliveredWithServiceLevel", "Payment has been delivered to creditor agent with service level."), + G006("DeliveredWIthoutServiceLevel", "Payment has been delivered to creditor agent without service level."), + ID01("CorrespondingOriginalFileStillNotSent", "Signature file was sent to the bank but the corresponding original file has not been sent yet."), + IEDT("IncorrectExpiryDateTime", "Expiry date time of the request-to-pay is incorrect."), + INAR("InvalidActivationReference", "Payer’s activation reference is invalid."), + INDT("InvalidDetails", "Details not valid for this field."), + IRNR("InitialRTPNeverReceived", "No initial request-to-pay has been received."), + ISWS("InvalidSettlementWindow", "Cannot schedule instruction for Night Window."), + MD01("NoMandate", "No Mandate"), + MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), + MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit"), + MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), + MD07("EndCustomerDeceased", "End customer is deceased."), + MINF("MissingInformation", "Information missing for the field or cannot be empty."), + MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), + MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), + NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), + NERI("NoERI", "Credit transfer is tagged as an Extended Remittance Information (ERI) transaction but does not contain ERI."), + NOAR("NonAgreedRTP", "No existing agreement for receiving request-to-pay messages."), + NOAS("NoAnswerFromCustomer", "No response from Beneficiary."), + NOCM("NotCompliantGeneric", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), + NOFR("OutstandingFundingForSettlement", "Continuous Processing Line on Hold Instruction."), + NOPG("NoPaymentGuarantee", "Requested payment guarantee (by Creditor) related to a request-to-pay cannot be provided."), + NRCH("PayerOrPayerRTPSPNotReachable", "Recipient side of the request-to-pay (payer or its request-to-pay service provider) is not reachable."), + OSNS("OptionalServiceNotSupported", "Requested optional service (for example instalment payments) is not supported."), + PINS("TypeOfPaymentInstrumentNotSupported", "Type of payment requested in the request-to-pay is not supported by the payer."), + RC01("BankIdentifierIncorrect", "Bank identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), + RC02("InvalidBankIdentifier", "Bank identifier is invalid or missing."), + RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing"), + RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing"), + RC05("InvalidBICIdentifier", "BIC identifier is invalid or missing."), + RC06("InvalidDebtorBICIdentifier", "Debtor BIC identifier is invalid or missing"), + RC07("InvalidCreditorBICIdentifier", "Creditor BIC identifier is invalid or missing"), + RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), + RC09("InvalidDebtorClearingSystemMemberIdentifier", "Debtor ClearingSystemMember identifier is invalid or missing"), + RC10("InvalidCreditorClearingSystemMemberIdentifier", "Creditor ClearingSystemMember identifier is invalid or missing"), + RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing"), + RC12("MissingCreditorSchemeId", "Creditor Scheme Id is invalid or missing"), + RC13("ParticipantNotAnActiveMemberofRTGS", "Originator not active any more."), + RC15("ParticipantNotActiveMemberSettlementType", "Settlement agreement required."), + RC16("ParticipantNotActiveMemberofSADCRTGS", "Participant blocked from SADC-RTGS."), + RCON("RMessageConflict", "Conflict with R-Message"), + RECI("ReceiverCustomerInformation", "Further information regarding the intended recipient."), + REPR("RTPReceivedCanBeProcessed", "Request-to-pay has been received and can be processed further."), + RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), + RQNR("RequestNotRecognized", "Payer did not recognize the request from Payee Participant,"), + RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), + RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), + RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), + RR04("RegulatoryReason", "Regulatory Reason"), + RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), + RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), + RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), + RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), + RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), + RR10("InvalidCharacterSet", "Character set supplied not valid for the country and payment type."), + RR11("InvalidDebtorAgentServiceID", "Invalid or missing identification of a bank proprietary service."), + RR12("InvalidPartyID", "Invalid or missing identification required within a particular country or payment type."), + RTNS("RTPNotSupportedForDebtor", "Debtor does not support request-to-pay transactions."), + RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), + S000("ValidRequestForCancellationAcknowledged", "Request for Cancellation is acknowledged following validation."), + S001("UETRFlaggedForCancellation", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been identified as being associated with a Request for Cancellation."), + S002("NetworkStopOfUETR", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been prevent from traveling across a messaging network."), + S003("RequestForCancellationForwarded", "Request for Cancellation has been forwarded to the payment processing/last payment processing agent."), + S004("RequestForCancellationDeliveryAcknowledgement", "Request for Cancellation has been acknowledged as delivered to payment processing/last payment processing agent."), + SBRN("SettlementBatchRemovalNotification", "Remove Concurrent Batch Processing Line on hold instruction."), + SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent."), + SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent."), + SL03("ServiceofClearingSystem", "Due to a specific service offered by the clearing system."), + SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), + SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), + SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), + SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), + SNRD("ServiceNotRendered", "Services are not yet rendered by the Payee Participant (Creditor)."), + SPII("RTPServiceProviderIdentifierIncorrect", "Identifier of the request-to-pay service provider is incorrect."), + TA01("TransmissonAborted", "The transmission of the file was not successful – it had to be aborted (for technical reasons)"), + TD01("NoDataAvailable", "There is no data available (for download)"), + TD02("FileNonReadable", "The file cannot be read (e.g. unknown format)"), + TD03("IncorrectFileStructure", "The file format is incomplete or invalid"), + TK01("TokenInvalid", "Token is invalid."), + TK02("SenderTokenNotFound", "Token used for the sender does not exist."), + TK03("ReceiverTokenNotFound", "Token used for the receiver does not exist."), + TK09("TokenMissing", "Token required for request is missing."), + TKCM("TokenCounterpartyMismatch", "Token found with counterparty mismatch."), + TKSG("TokenSingleUse", "Single Use Token already used."), + TKSP("TokenSuspended", "Token found with suspended status."), + TKVE("TokenValueLimitExceeded", "Token found with value limit rule violation."), + TKXP("TokenExpired", "Token expired."), + TM01("InvalidCutOffTime", "Associated message, payment information block, or transaction was received after agreed processing cut-off time."), + TS01("TransmissionSuccessful", "The (technical) transmission of the file was successful."), + TS04("TransferToSignByHand", "The order was transferred to pass by accompanying note signed by hand"), + UCRD("UnknownCreditor", "Unknown Creditor."), + UPAY("UnduePayment", "Payment is not justified."), +} + +enum class ExternalPaymentGroupStatusCode(val isoCode: String, val description: String) { + ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), + ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), + ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement on the debtor's account has been completed."), + ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment initiation has been accepted for execution."), + ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), + ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), + PART("PartiallyAccepted", "A number of transactions have been accepted, whereas another number of transactions have not yet achieved"), + PDNG("Pending", "Payment initiation or individual transaction included in the payment initiation is pending. Further checks and status update will be performed."), + RCVD("Received", "Payment initiation has been received by the receiving agent"), + RJCT("Rejected", "Payment initiation or individual transaction included in the payment initiation has been rejected."), +} + +enum class ExternalPaymentTransactionStatusCode(val isoCode: String, val description: String) { + ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), + ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), + ACFC("AcceptedFundsChecked", "Preceding check of technical validation and customer profile was successful and an automatic funds check was positive."), + ACIS("AcceptedandChequeIssued", "Payment instruction to issue a cheque has been accepted, and the cheque has been issued but not yet been deposited or cleared."), + ACPD("AcceptedClearingProcessed", "Status of transaction released from the Debtor Agent and accepted by the clearing."), + ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement completed."), + ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment instruction has been accepted for execution."), + ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), + ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), + ACWP("AcceptedWithoutPosting", "Payment instruction included in the credit transfer is accepted without being posted to the creditor customer’s account."), + BLCK("Blocked", "Payment transaction previously reported with status 'ACWP' is blocked, for example, funds will neither be posted to the Creditor's account, nor be returned to the Debtor."), + CANC("Cancelled", "Payment initiation has been successfully cancelled after having received a request for cancellation."), + CPUC("CashPickedUpByCreditor", "Cash has been picked up by the Creditor."), + PATC("PartiallyAcceptedTechnicalCorrect", "Payment initiation needs multiple authentications, where some but not yet all have been performed. Syntactical and semantical validations are successful."), + PDNG("Pending", "Payment instruction is pending. Further checks and status update will be performed."), + PRES("Presented", "Request for Payment has been presented to the Debtor."), + RCVD("Received", "Payment instruction has been received."), + RJCT("Rejected", "Payment instruction has been rejected."), +} + +enum class ExternalReturnReasonCode(val isoCode: String, val description: String) { + AC01("IncorrectAccountNumber", "Format of the account number specified is not correct"), + AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing."), + AC03("InvalidCreditorAccountNumber", "Wrong IBAN in SCT"), + AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books"), + AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), + AC07("ClosedCreditorAccountNumber", "Creditor account number closed."), + AC13("InvalidDebtorAccountType", "Debtor account type is missing or invalid"), + AC14("InvalidAgent", "An agent in the payment chain is invalid."), + AC15("AccountDetailsChanged", "Account details have changed."), + AC16("AccountInSequestration", "Account is in sequestration."), + AC17("AccountInLiquidation", "Account is in liquidation."), + AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), + AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), + AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), + AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect."), + AM01("ZeroAmount", "Specified message amount is equal to zero"), + AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), + AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), + AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), + AM05("Duplication", "Duplication"), + AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), + AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), + AM09("WrongAmount", "Amount received is not the amount agreed or expected"), + AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), + ARDT("AlreadyReturnedTransaction", "Already returned original SCT"), + BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number, organisation ID or private ID."), + BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), + BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), + BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), + BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), + BE08("BankError", "Returned as a result of a bank error."), + BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid."), + BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid."), + BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid."), + BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid."), + CN01("AuthorisationCancelled", "Authorisation is cancelled."), + CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), + CNPC("CashNotPickedUp", "Cash not picked up by Creditor or cash could not be delivered to Creditor"), + CURR("IncorrectCurrency", "Currency of the payment is incorrect"), + CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), + DC04("NoCustomerCreditTransferReceived", "Return of Covering Settlement due to the underlying Credit Transfer details not being received."), + DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), + DS28("ReturnForTechnicalReason", "Return following technical problems resulting in erroneous transaction."), + DT01("InvalidDate", "Invalid date (eg, wrong settlement date)"), + DT02("ChequeExpired", "Cheque has been issued but not deposited and is considered expired."), + DT04("FutureDateNotSupported", "Future date not supported."), + DUPL("DuplicatePayment", "Payment is a duplicate of another payment."), + ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), + ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), + ED05("SettlementFailed", "Settlement of the transaction has failed."), + EMVL("EMVLiabilityShift", "The card payment is fraudulent and was not processed with EMV technology for an EMV card."), + ERIN("ERIOptionNotSupported", "The Extended Remittance Information (ERI) option is not supported."), + FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), + FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid."), + FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), + FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid."), + FF07("InvalidPurpose", "Purpose is missing or invalid."), + FOCR("FollowingCancellationRequest", "Return following a cancellation request"), + FR01("Fraud", "Returned as a result of fraud."), + FRTR("FinalResponseMandateCancelled", "Final response/tracking is recalled as mandate is cancelled."), + G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), + MD01("NoMandate", "No Mandate"), + MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), + MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit."), + MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), + MD07("EndCustomerDeceased", "End customer is deceased."), + MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), + MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), + NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), + NOAS("NoAnswerFromCustomer", "No response from Beneficiary"), + NOCM("NotCompliant", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), + NOOR("NoOriginalTransactionReceived", "Original SCT never received"), + PINL("PINLiabilityShift", "The card payment is fraudulent (lost and stolen fraud) and was processed as EMV transaction without PIN verification."), + RC01("BankIdentifierIncorrect", "Bank Identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), + RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing."), + RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing."), + RC07("InvalidCreditorBICIdentifier", "Incorrrect BIC of the beneficiary Bank in the SCTR"), + RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), + RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing."), + RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), + RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), + RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), + RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), + RR04("RegulatoryReason", "Regulatory Reason"), + RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), + RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), + RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), + RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), + RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), + RR11("InvalidDebtorAgentServiceIdentification", "Invalid or missing identification of a bank proprietary service."), + RR12("InvalidPartyIdentification", "Invalid or missing identification required within a particular country or payment type."), + RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), + SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent"), + SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent"), + SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), + SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), + SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), + SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), + SP01("PaymentStopped", "Payment is stopped by account holder."), + SP02("PreviouslyStopped", "Previously stopped by means of a stop payment advise."), + SVNR("ServiceNotRendered", "The card payment is returned since a cash amount rendered was not correct or goods or a service was not rendered to the customer, e.g. in an e-commerce situation."), + TM01("CutOffTime", "Associated message was received after agreed processing cut-off time."), + TRAC("RemovedFromTracking", "Return following direct debit being removed from tracking process."), + UPAY("UnduePayment", "Payment is not justified."), +} + diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/camt.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/camt.kt @@ -0,0 +1,551 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ +package tech.libeufin.nexus.iso20022 + +import tech.libeufin.common.* +import tech.libeufin.nexus.* +import tech.libeufin.nexus.ebics.Dialect +import java.io.InputStream +import java.time.Instant +import java.time.ZoneOffset + +sealed interface TxNotification { + val executionTime: Instant +} + +/** ISO20022 incoming payment */ +data class IncomingPayment( + /** ISO20022 UETR or TxID */ + val bankId: String? = null, // Null when TxID is wrong with Atruvia's implementation of instant transactions + val amount: TalerAmount, + val subject: String, + override val executionTime: Instant, + val debtorPayto: IbanPayto +): TxNotification { + override fun toString(): String { + return "IN ${executionTime.fmtDate()} $amount $bankId debitor=$debtorPayto subject=\"$subject\"" + } +} + +/** ISO20022 outgoing payment */ +data class OutgoingPayment( + /** ISO20022 EndToEndId or MessageId (retrocompatibility) */ + val endToEndId: String, + /** ISO20022 MessageId */ + val msgId: String? = null, + val amount: TalerAmount, + val subject: String? = null, // Some implementation does not provide this for recovery + override val executionTime: Instant, + val creditorPayto: IbanPayto? = null // Some implementation does not provide this for recovery +): TxNotification { + override fun toString(): String { + val msgIdFmt = if (msgId == null) "" else "$msgId." + return "OUT ${executionTime.fmtDate()} $amount $msgIdFmt$endToEndId creditor=$creditorPayto subject=\"$subject\"" + } +} + +/** ISO20022 outgoing batch */ +data class OutgoingBatch( + /** ISO20022 MessageId */ + val msgId: String, + override val executionTime: Instant, +): TxNotification { + override fun toString(): String { + return "BATCH ${executionTime.fmtDate()} $msgId" + } +} + +/** ISO20022 outgoing reversal */ +data class OutgoingReversal( + /** ISO20022 EndToEndId */ + val endToEndId: String, + /** ISO20022 MessageId */ + val msgId: String? = null, + val reason: String?, + override val executionTime: Instant +): TxNotification { + override fun toString(): String { + val msgIdFmt = if (msgId == null) "" else "$msgId." + return "BOUNCE ${executionTime.fmtDate()} $msgIdFmt$endToEndId: $reason" + } +} + +private class TxErr(val msg: String): Exception(msg) + +private enum class Kind { + CRDT, + DBIT +} + +/** Unique ID generated by libeufin-nexus */ +private data class OutgoingId( + // Unique msg ID generated by libeufin-nexus + val msgId: String?, + // Unique end-to-end ID generated by libeufin-nexus + val endToEndId: String? +) { + fun ref(): String? = endToEndId ?: msgId +} + +/** Parse a payto */ +private fun XmlDestructor.payto(prefix: String): IbanPayto? { + return opt("RltdPties") { + val iban = opt("${prefix}Acct")?.one("Id")?.one("IBAN")?.text() + if (iban != null) { + val name = opt(prefix) { opt("Nm")?.text() ?: opt("Pty")?.one("Nm")?.text() } + // TODO more performant option + ibanPayto(iban, name) + } else { + null + } + } +} + +/** Check if an entry status is BOOK */ +private fun XmlDestructor.isBooked(): Boolean { + // We check at the Sts or Sts/Cd level for retrocompatibility + return one("Sts") { + val status = opt("Cd")?.text() ?: text() + status == "BOOK" + } +} + +/** Parse the instruction execution date */ +private fun XmlDestructor.executionDate(): Instant { + // Value date if present else booking date + val date = opt("ValDt") ?: one("BookgDt") + val parsed = date.opt("Dt") { + date().atStartOfDay() + } ?: date.one("DtTm") { + dateTime() + } + return parsed.toInstant(ZoneOffset.UTC) +} + +/** Parse batch message ID and transaction end-to-end ID as generated by libeufin-nexus */ +private fun XmlDestructor.outgoingId(): OutgoingId = one("Refs") { + val endToEndId = opt("EndToEndId")?.text() + val msgId = opt("MsgId")?.text() + if (endToEndId == null) { + // This is a batch representation + OutgoingId(msgId, null) + } else if (endToEndId == "NOTPROVIDED") { + // If not set use MsgId as end-to-end ID for retrocompatibility + OutgoingId(msgId, msgId) + } else { + OutgoingId(msgId, endToEndId) + } +} + +/** Parse and format transaction return reasons */ +private fun XmlDestructor.returnReason(): String = opt("RtrInf") { + val code = one("Rsn").one("Cd").enum<ExternalReturnReasonCode>() + val info = map("AddtlInf") { text() }.joinToString("") + buildString { + append("${code.isoCode} '${code.description}'") + if (info.isNotEmpty()) { + append(" - '$info'") + } + } +} ?: opt("RmtInf") { + map("Ustrd") { text() }.joinToString("") +} ?: "" + +/** Parse amount */ +private fun XmlDestructor.amount(acceptedCurrency: String) = one("Amt") { + val currency = attr("Ccy") + /** FIXME: test by sending non-CHF to PoFi and see which currency gets here. */ + if (currency != acceptedCurrency) throw Exception("Currency $currency not supported") + TalerAmount("$currency:${text()}") +} + +/** Parse bank transaction code */ +private fun XmlDestructor.bankTransactionCode(): BankTransactionCode { + return one("BkTxCd").one("Domn") { + val domain = one("Cd").enum<ExternalBankTransactionDomainCode>() + one("Fmly") { + val family = one("Cd").enum<ExternalBankTransactionFamilyCode>() + val subFamily = one("SubFmlyCd").enum<ExternalBankTransactionSubFamilyCode>() + + BankTransactionCode(domain, family, subFamily) + } + } +} + +/** Parse optional bank transaction code */ +private fun XmlDestructor.optBankTransactionCode(): BankTransactionCode? { + return opt("BkTxCd")?.one("Domn") { + val domain = one("Cd").enum<ExternalBankTransactionDomainCode>() + one("Fmly") { + val family = one("Cd").enum<ExternalBankTransactionFamilyCode>() + val subFamily = one("SubFmlyCd").enum<ExternalBankTransactionSubFamilyCode>() + + BankTransactionCode(domain, family, subFamily) + } + } +} + +/** Parse transaction wire transfer subject */ +private fun XmlDestructor.wireTransferSubject(): String? { + return opt("RmtInf")?.map("Ustrd") { text() }?.joinToString("")?.trim() +} + +/** Parse camt.054 or camt.053 file */ +fun parseTx( + notifXml: InputStream, + acceptedCurrency: String, + dialect: Dialect +): List<TxNotification> { + /* + In ISO 20022 specifications, most fields are optional and the same information + can be written several times in different places. For libeufin, we're only + interested in a subset of the available values that can be found in both camt.052, + camt.053 and camt.054. This function should not fail on legitimate files and should + simply warn when available information are insufficient. + + EBICS and ISO20022 do not provide a perfect transaction identifier. The best is the + UETR (unique end-to-end transaction reference), which is a universally unique + identifier (UUID). However, it is not supplied by all banks. TxId (TransactionIdentification) + is a unique identification as assigned by the first instructing agent. As its format + is ambiguous, its uniqueness is not guaranteed by the standard, and it is only + supposed to be unique for a “pre-agreed period”, whatever that means. These two + identifiers are optional in the standard, but have the advantage of being unique + and can be used to track a transaction between banks so we use them when available. + + It is also possible to use AccountServicerReference, which is a unique reference + assigned by the account servicing institution. They can be present at several levels + (batch level, transaction level, etc.) and are often optional. They also have the + disadvantage of being known only by the account servicing institution. They should + therefore only be used as a last resort. + */ + + val txsInfo = mutableListOf<TxInfo>() + XmlDestructor.fromStream(notifXml, "Document") { when (dialect) { + Dialect.gls -> { + /** Common parsing logic for camt.052 and camt.053 */ + fun XmlDestructor.parseGlsInner() { + opt("Acct") { + // Sanity check on currency and IBAN ? + } + each("Ntry") { + if (!isBooked()) return@each + val code = bankTransactionCode() + if (!code.isPayment()) return@each + val entryRef = opt("AcctSvcrRef")?.text() + val bookDate = executionDate() + val kind = one("CdtDbtInd").enum<Kind>() + val amount = amount(acceptedCurrency) + one("NtryDtls").one("TxDtls") { // TODO handle batches + val code = optBankTransactionCode() ?: code + val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() + if (code.isReversal()) { + val outgoingId = outgoingId() + if (kind == Kind.CRDT) { + val reason = returnReason() + txsInfo.add(TxInfo.CreditReversal( + ref = outgoingId.ref() ?: txRef ?: entryRef, + bookDate = bookDate, + id = outgoingId, + reason = reason, + code = code + )) + } + } else { + val subject = wireTransferSubject() + when (kind) { + Kind.CRDT -> { + val bankId = one("Refs").opt("TxId")?.text() + val debtorPayto = payto("Dbtr") + txsInfo.add(TxInfo.Credit( + ref = bankId ?: txRef ?: entryRef, + bookDate = bookDate, + bankId = bankId, + amount = amount, + subject = subject, + debtorPayto = debtorPayto, + code = code + )) + } + Kind.DBIT -> { + val outgoingId = outgoingId() + val creditorPayto = payto("Cdtr") + txsInfo.add(TxInfo.Debit( + ref = outgoingId.ref() ?: txRef ?: entryRef, + bookDate = bookDate, + id = outgoingId, + amount = amount, + subject = subject, + creditorPayto = creditorPayto, + code = code + )) + } + } + } + } + } + } + opt("BkToCstmrStmt")?.each("Stmt") { // Camt.053 + // All transactions appear here the day after they are booked + parseGlsInner() + } + opt("BkToCstmrAcctRpt")?.each("Rpt") { // Camt.052 + // Transactions might appear here first before the end of the day + parseGlsInner() + } + opt("BkToCstmrDbtCdtNtfctn")?.each("Ntfctn") { // Camt.054 + // Instant transactions appear here a few seconds after being booked + opt("Acct") { + // Sanity check on currency and IBAN ? + } + each("Ntry") { + if (!isBooked()) return@each + val code = bankTransactionCode() + if (code.isReversal() || !code.isPayment()) return@each + val entryRef = opt("AcctSvcrRef")?.text() + val bookDate = executionDate() + val kind = one("CdtDbtInd").enum<Kind>() + val amount = amount(acceptedCurrency) + one("NtryDtls").one("TxDtls") { + val code = optBankTransactionCode() ?: code + val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() + val subject = wireTransferSubject() + if (kind == Kind.CRDT) { + val bankId = one("Refs").opt("TxId")?.text() + val debtorPayto = payto("Dbtr") + txsInfo.add(TxInfo.Credit( + ref = txRef ?: entryRef, + bookDate = bookDate, + // TODO use the bank ID again when Atruvia's implementation is fixed + bankId = null, + amount = amount, + subject = subject, + debtorPayto = debtorPayto, + code = code + )) + } + } + } + } + } + Dialect.postfinance -> { + opt("BkToCstmrStmt")?.each("Stmt") { // Camt.053 + /* + All transactions appear here on the day following their booking. Alas, some + necessary metadata is missing, which is only present in camt.054. However, + this file contains the structured return reasons that are missing from the + camt.054 files. That's why we only use this file for this purpose. + */ + opt("Acct") { + // Sanity check on currency and IBAN ? + } + each("Ntry") { + if (!isBooked()) return@each + val code = bankTransactionCode() + // Non reversal transaction are handled in camt.054 + if (!(code.isReversal() && code.isPayment())) return@each + + val entryRef = opt("AcctSvcrRef")?.text() + val bookDate = executionDate() + one("NtryDtls").one("TxDtls") { + val kind = one("CdtDbtInd").enum<Kind>() + val code = optBankTransactionCode() ?: code + if (kind == Kind.CRDT) { + val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() + val outgoingId = outgoingId() + val reason = returnReason() + txsInfo.add(TxInfo.CreditReversal( + ref = outgoingId.ref() ?: txRef ?: entryRef, + bookDate = bookDate, + id = outgoingId, + reason = reason, + code = code + )) + } + } + } + } + opt("BkToCstmrDbtCdtNtfctn")?.each("Ntfctn") { // Camt.054 + // Instant transactions appear here a moment after being booked + opt("Acct") { + // Sanity check on currency and IBAN ? + } + each("Ntry") { + if (!isBooked()) return@each + val code = bankTransactionCode() + // Reversal are handled from camt.053 + if (code.isReversal() || !code.isPayment()) return@each + + val entryRef = opt("AcctSvcrRef")?.text() + val bookDate = executionDate() + one("NtryDtls").each("TxDtls") { + val kind = one("CdtDbtInd").enum<Kind>() + val code = optBankTransactionCode() ?: code + val amount = amount(acceptedCurrency) + val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text() + val subject = wireTransferSubject() + when (kind) { + Kind.CRDT -> { + val bankId = opt("Refs")?.opt("UETR")?.text() + val debtorPayto = payto("Dbtr") + txsInfo.add(TxInfo.Credit( + ref = bankId ?: txRef ?: entryRef, + bookDate = bookDate, + bankId = bankId, + amount = amount, + subject = subject, + debtorPayto = debtorPayto, + code = code + )) + } + Kind.DBIT -> { + val outgoingId = outgoingId() + val creditorPayto = payto("Cdtr") + txsInfo.add(TxInfo.Debit( + ref = outgoingId.ref() ?: txRef ?: entryRef, + bookDate = bookDate, + id = outgoingId, + amount = amount, + subject = subject, + creditorPayto = creditorPayto, + code = code + )) + } + } + } + } + } + } + }} + + return txsInfo.mapNotNull { + try { + parseTxLogic(it) + } catch (e: TxErr) { + // TODO: add more info in doc or in log message? + logger.warn("skip incomplete tx: ${e.msg}") + null + } + } +} + +private sealed interface TxInfo { + // Bank provider ref for debugging + val ref: String? + // When was this transaction booked + val bookDate: Instant + // ISO20022 bank transaction code + val code: BankTransactionCode + data class CreditReversal( + override val ref: String?, + override val bookDate: Instant, + override val code: BankTransactionCode, + // Unique ID generated by libeufin-nexus + val id: OutgoingId, + val reason: String + ): TxInfo + data class Credit( + override val ref: String?, + override val bookDate: Instant, + override val code: BankTransactionCode, + // Unique ID generated by payment provider + val bankId: String?, + val amount: TalerAmount, + val subject: String?, + val debtorPayto: IbanPayto? + ): TxInfo + data class Debit( + override val ref: String?, + override val bookDate: Instant, + override val code: BankTransactionCode, + // Unique ID generated by libeufin-nexus + val id: OutgoingId, + val amount: TalerAmount, + val subject: String?, + val creditorPayto: IbanPayto? + ): TxInfo +} + +private fun parseTxLogic(info: TxInfo): TxNotification { + return when (info) { + is TxInfo.CreditReversal -> { + if (info.id.endToEndId == null) + throw TxErr("missing end-to-end ID for Credit reversal ${info.ref}") + OutgoingReversal( + endToEndId = info.id.endToEndId!!, + msgId = info.id.msgId, + reason = info.reason, + executionTime = info.bookDate + ) + } + is TxInfo.Credit -> { + /*if (info.bankId == null) TODO use the bank ID again when Atruvia's implementation is fixed + throw TxErr("missing bank ID for Credit ${info.ref}")*/ + if (info.subject == null) + throw TxErr("missing subject for Credit ${info.ref}") + if (info.debtorPayto == null) + throw TxErr("missing debtor info for Credit ${info.ref}") + IncomingPayment( + amount = info.amount, + bankId = info.bankId, + debtorPayto = info.debtorPayto, + executionTime = info.bookDate, + subject = info.subject + ) + } + is TxInfo.Debit -> { + if (info.id.endToEndId == null && info.id.msgId == null) { + throw TxErr("missing end-to-end ID for Debit ${info.ref}") + } else if (info.id.endToEndId != null) { + OutgoingPayment( + amount = info.amount, + endToEndId = info.id.endToEndId, + msgId = info.id.msgId, + executionTime = info.bookDate, + creditorPayto = info.creditorPayto, + subject = info.subject + ) + } else { + OutgoingBatch( + msgId = info.id.msgId!!, + executionTime = info.bookDate, + ) + } + } + } +} + +data class BankTransactionCode( + val domain: ExternalBankTransactionDomainCode, + val family: ExternalBankTransactionFamilyCode, + val subFamily: ExternalBankTransactionSubFamilyCode +) { + fun isReversal(): Boolean = REVERSAL_CODE.contains(subFamily) + fun isPayment(): Boolean = domain == ExternalBankTransactionDomainCode.PMNT || subFamily == ExternalBankTransactionSubFamilyCode.PSTE + + override fun toString(): String = + "${domain.name} ${family.name} ${subFamily.name} - '${domain.description}' '${family.description}' '${subFamily.description}'" + + companion object { + private val REVERSAL_CODE = setOf( + ExternalBankTransactionSubFamilyCode.RPCR, + ExternalBankTransactionSubFamilyCode.RRTN, + ExternalBankTransactionSubFamilyCode.PSTE, + ) + } +} +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/hac.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/hac.kt @@ -0,0 +1,72 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ +package tech.libeufin.nexus.iso20022 + +import tech.libeufin.nexus.* +import java.io.InputStream +import java.time.Instant +import java.time.ZoneOffset + +data class CustomerAck( + val actionType: HacAction, + val orderId: String?, + val code: ExternalStatusReasonCode?, + val info: String, + val timestamp: Instant +) { + fun msg(): String = buildString { + append("$actionType") + if (code != null) append(" ${code.isoCode}") + append(" - '${actionType.description}'") + if (code != null) append(" '${code.description}'") + if (info != "") append(" - '$info'") + } + + override fun toString(): String = buildString { + append(timestamp.fmtDateTime()) + if (orderId != null) append(" $orderId") + append(" ${msg()}") + } +} + +/** Parse HAC pain.002 XML file */ +fun parseCustomerAck(xml: InputStream): List<CustomerAck> { + return XmlDestructor.fromStream(xml, "Document") { + one("CstmrPmtStsRpt").map("OrgnlPmtInfAndSts") { + val actionType = one("OrgnlPmtInfId").enum<HacAction>() + one("StsRsnInf") { + var timestamp: Instant? = null + var orderId: String? = null + one("Orgtr").one("Id").one("OrgId").each("Othr") { + val value = one("Id") + val key = one("SchmeNm").one("Prtry").text() + when (key) { + "TimeStamp" -> { + timestamp = value.dateTime().toInstant(ZoneOffset.UTC) + } + "OrderID" -> orderId = value.text() + } + } + val code = opt("Rsn")?.one("Cd")?.enum<ExternalStatusReasonCode>() + val info = map("AddtlInf") { text() }.joinToString("") + CustomerAck(actionType, orderId, code, info, requireNotNull(timestamp)) + } + } + } +} +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain001.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain001.kt @@ -0,0 +1,126 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ +package tech.libeufin.nexus.iso20022 + +import tech.libeufin.common.* +import tech.libeufin.nexus.* +import tech.libeufin.nexus.ebics.Dialect +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +/** String representation of a Taler [amount] compatible with EBICS */ +fun getAmountNoCurrency(amount: TalerAmount): String { + if (amount.isSubCent()) { + throw Exception("Sub-cent amounts not supported") + } + return amount.number().toString() +} + +/** pain.001 transaction metadata */ +data class Pain001Tx( + val creditor: IbanAccountMetadata, + val amount: TalerAmount, + val subject: String, + val endToEndId: String +) + +/** pain.001 message metadata */ +data class Pain001Msg( + val messageId: String, + val timestamp: Instant, + val debtor: IbanAccountMetadata, + val sum: TalerAmount, + val txs: List<Pain001Tx> +) + +/** Create a pain.001 XML document [msg] valid for [dialect] */ +fun createPain001( + msg: Pain001Msg, + dialect: Dialect +): ByteArray { + val version = "09" + val zonedTimestamp = ZonedDateTime.ofInstant(msg.timestamp, ZoneId.of("UTC")) + val totalAmount = getAmountNoCurrency(msg.sum) + return XmlBuilder.toBytes("Document") { + attr("xmlns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version") + attr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + attr("xsi:schemaLocation", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version pain.001.001.$version.xsd") + el("CstmrCdtTrfInitn") { + el("GrpHdr") { + // Used for idempotency as banks will refuse to process EBICS request with the same MsgId for a pre-agreed period + // Used to uniquely identify batches of transactions in other files + el("MsgId", msg.messageId) + el("CreDtTm", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(zonedTimestamp)) + el("NbOfTxs", msg.txs.size.toString()) + el("CtrlSum", totalAmount) + el("InitgPty/Nm", msg.debtor.name) + } + el("PmtInf") { + el("PmtInfId", "NOTPROVIDED") + el("PmtMtd", "TRF") + el("BtchBookg", "false") + el("NbOfTxs", msg.txs.size.toString()) + el("CtrlSum", totalAmount) + el("PmtTpInf/SvcLvl/Cd", + when (dialect) { + Dialect.postfinance -> "SDVA" + Dialect.gls -> "SEPA" + } + ) + el("ReqdExctnDt/Dt", DateTimeFormatter.ISO_DATE.format(zonedTimestamp)) + el("Dbtr/Nm", msg.debtor.name) + el("DbtrAcct/Id/IBAN", msg.debtor.iban) + el("DbtrAgt/FinInstnId") { + if (msg.debtor.bic != null) { + el("BICFI", msg.debtor.bic) + } else { + el("Othr/Id", "NOTPROVIDED") + } + } + el("ChrgBr", "SLEV") + for (tx in msg.txs) { + el("CdtTrfTxInf") { + el("PmtId") { + el("InstrId", tx.endToEndId) + // Used to uniquely identify transactions in other files + el("EndToEndId", tx.endToEndId) + } + el("Amt/InstdAmt") { + attr("Ccy", tx.amount.currency) + text(getAmountNoCurrency(tx.amount)) + } + if (tx.creditor.bic != null) el("CdtrAgt/FinInstnId/BICFI", tx.creditor.bic) + el("Cdtr") { + el("Nm", tx.creditor.name) + // Addr might become a requirement in the future + /*el("PstlAdr") { + el("TwnNm", "Bochum") + el("Ctry", "DE") + }*/ + } + el("CdtrAcct/Id/IBAN", tx.creditor.iban) + el("RmtInf/Ustrd", tx.subject) + } + } + } + } + } +} +\ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain002.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain002.kt @@ -0,0 +1,148 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ +package tech.libeufin.nexus.iso20022 + +import tech.libeufin.nexus.* +import java.io.InputStream + +private fun fmtMsg(code: String?, description: String?, reasons: List<Reason>) = buildString { + if (code != null) { + append(code) + append(" ") + if (description != null) { + append("'") + append(description) + append("'") + } + if (reasons.isNotEmpty()) { + append(":") + } + } + for (reason in reasons) { + append(" ") + append(reason.code.isoCode) + append(" '") + append(reason.code.description) + append("'") + if (reason.information.isNotEmpty()) { + append(" '") + append(reason.information) + append("'") + } + } +} + +data class MsgStatus( + val id: String, + val code: ExternalPaymentGroupStatusCode?, + val reasons: List<Reason>, + val payments: List<PmtStatus> +) { + fun msg() = fmtMsg(code?.isoCode, code?.description, reasons) + override fun toString() = buildString { + append(id) + val msg = msg() + if (msg.isNotEmpty()) { + append(" ") + append(msg) + } + for (pmt in payments) { + append("\n>") + append(pmt.id) + val msg = pmt.msg() + if (msg.isNotEmpty()) { + append(" ") + append(msg) + } + + for (tx in pmt.transactions) { + append("\n>>") + if (tx.id != tx.endToEndId) { + append(tx.id) + append(" ") + } + append(tx.endToEndId) + val msg = tx.msg() + if (msg.isNotEmpty()) { + append(" ") + append(msg) + } + } + } + } +} + +data class PmtStatus( + val id: String, + val code: ExternalPaymentGroupStatusCode?, + val reasons: List<Reason>, + val transactions: List<TxStatus> +) { + fun msg() = fmtMsg(code?.isoCode, code?.description, reasons) +} + +data class TxStatus( + val id: String, + val endToEndId: String, + val code: ExternalPaymentTransactionStatusCode, + val reasons: List<Reason> +) { + fun msg() = fmtMsg(code?.isoCode, code?.description, reasons) +} + +data class Reason ( + val code: ExternalStatusReasonCode, + val information: String +) + +/** Parse pain.002 XML file */ +fun parseCustomerPaymentStatusReport(xml: InputStream): MsgStatus { + fun XmlDestructor.reasons(): List<Reason> { + return map("StsRsnInf") { + val code = one("Rsn").one("Cd").enum<ExternalStatusReasonCode>() + val info = map("AddtlInf") { text() }.joinToString("") + Reason(code, info) + } + } + + return XmlDestructor.fromStream(xml, "Document") { + one("CstmrPmtStsRpt") { + val (id, code, reasons) = one("OrgnlGrpInfAndSts") { + val id = one("OrgnlMsgId").text() + val code = opt("GrpSts")?.enum<ExternalPaymentGroupStatusCode>() + val reasons = reasons() + Triple(id, code, reasons) + } + val payments = map("OrgnlPmtInfAndSts") { + val id = one("OrgnlPmtInfId").text() + val code = opt("PmtInfSts")?.enum<ExternalPaymentGroupStatusCode>() + val reasons = reasons() + val transactions = map("TxInfAndSts") { + val id = one("OrgnlInstrId").text() + val endToEndId = one("OrgnlEndToEndId").text() + val code = one("TxSts").enum<ExternalPaymentTransactionStatusCode>() + val reasons = reasons() + TxStatus(id, endToEndId, code, reasons) + } + PmtStatus(id, code, reasons, transactions) + } + MsgStatus(id, code, reasons, payments) + } + } +} +\ No newline at end of file diff --git a/nexus/src/test/kotlin/CliTest.kt b/nexus/src/test/kotlin/CliTest.kt @@ -146,8 +146,8 @@ class CliTest { // Check empty check() // Check with transactions - ingestIn(db) - ingestOut(db) + registerIn(db) + registerOut(db) check() // Check with taler transactions talerableOut(db) diff --git a/nexus/src/test/kotlin/DatabaseTest.kt b/nexus/src/test/kotlin/DatabaseTest.kt @@ -19,62 +19,19 @@ import org.junit.Test import tech.libeufin.common.* -import tech.libeufin.common.db.one -import tech.libeufin.common.db.withStatement +import tech.libeufin.common.db.* import tech.libeufin.nexus.AccountType import tech.libeufin.nexus.NexusIngestConfig -import tech.libeufin.nexus.cli.ingestIncomingPayment -import tech.libeufin.nexus.cli.ingestOutgoingPayment -import tech.libeufin.nexus.cli.ingestTransaction -import tech.libeufin.nexus.db.Database +import tech.libeufin.nexus.iso20022.* +import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.cli.* +import tech.libeufin.nexus.db.* +import tech.libeufin.nexus.db.PaymentDAO.OutgoingRegistrationResult import tech.libeufin.nexus.db.InitiatedDAO.PaymentInitiationResult import java.time.Instant import kotlin.test.* -class OutgoingPaymentsTest { - @Test - fun register() = setup { db, _ -> - // With reconciling - genOutPay("paid by nexus").run { - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay("waiting for reconciliation", messageId)) - ) - db.payment.registerOutgoing(this, null, null).run { - assertTrue(new) - assertTrue(initiated) - } - db.payment.registerOutgoing(this, null, null).run { - assertFalse(new) - assertTrue(initiated) - } - } - // Without reconciling - genOutPay("not paid by nexus").run { - db.payment.registerOutgoing(this, null, null).run { - assertTrue(new) - assertFalse(initiated) - } - db.payment.registerOutgoing(this, null, null).run { - assertFalse(new) - assertFalse(initiated) - } - } - } - - @Test - fun talerable() = setup { db, _ -> - val wtid = ShortHashCode.rand() - val url = "https://exchange.com" - genOutPay("$wtid $url").run { - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay("waiting for reconciliation", messageId)) - ) - ingestOutgoingPayment(db, this) - } - } -} - -suspend fun Database.getCount(): Triple<Int, Int, Int> = serializable( +suspend fun Database.checkInCount(nbIncoming: Int, nbBounce: Int, nbTalerable: Int) = serializable( """ SELECT (SELECT count(*) FROM incoming_transactions) AS incoming, (SELECT count(*) FROM bounced_transactions) AS bounce, @@ -82,12 +39,25 @@ suspend fun Database.getCount(): Triple<Int, Int, Int> = serializable( """ ) { one { - Triple(it.getInt("incoming"), it.getInt("bounce"), it.getInt("talerable")) + assertEquals( + Triple(nbIncoming, nbBounce, nbTalerable), + Triple(it.getInt("incoming"), it.getInt("bounce"), it.getInt("talerable")) + ) } } -suspend fun Database.checkCount(nbIncoming: Int, nbBounce: Int, nbTalerable: Int) { - assertEquals(Triple(nbIncoming, nbBounce, nbTalerable), getCount()) +suspend fun Database.checkOutCount(nbIncoming: Int, nbTalerable: Int) = serializable( + """ + SELECT (SELECT count(*) FROM outgoing_transactions) AS incoming, + (SELECT count(*) FROM talerable_outgoing_transactions) AS talerable; + """ +) { + one { + assertEquals( + Pair(nbIncoming, nbTalerable), + Pair(it.getInt("incoming"), it.getInt("talerable")) + ) + } } suspend fun Database.inTxExists(id: String): Boolean = serializable( @@ -99,25 +69,105 @@ suspend fun Database.inTxExists(id: String): Boolean = serializable( } } +class OutgoingPaymentsTest { + @Test + fun registerTx() = setup { db, _ -> + // Register initiated transaction + for (subject in sequenceOf( + "initiated by nexus", + "${ShortHashCode.rand()} https://exchange.com" + )) { + val pay = genOutPay(subject) + assertIs<PaymentInitiationResult.Success>( + db.initiated.create(genInitPay(pay.endToEndId, subject)) + ) + val first = registerOutgoingPayment(db, pay) + assertEquals(OutgoingRegistrationResult(id = first.id, initiated = true, new = true), first) + assertEquals( + OutgoingRegistrationResult(id = first.id, initiated = true, new = false), + registerOutgoingPayment(db, pay) + ) + } + db.checkOutCount(nbIncoming = 2, nbTalerable = 1) + + // Register unknown + for (subject in sequenceOf( + "not initiated by nexus", + "${ShortHashCode.rand()} https://exchange.com" + )) { + val pay = genOutPay(subject) + val first = registerOutgoingPayment(db, pay) + assertEquals(OutgoingRegistrationResult(id = first.id, initiated = false, new = true), first) + assertEquals( + OutgoingRegistrationResult(id = first.id, initiated = false, new = false), + registerOutgoingPayment(db, pay) + ) + } + db.checkOutCount(nbIncoming = 4, nbTalerable = 2) + + // Register wtid reuse + val wtid = ShortHashCode.rand() + for (subject in sequenceOf( + "$wtid https://exchange.com", + "$wtid https://exchange.com" + )) { + val pay = genOutPay(subject) + val first = registerOutgoingPayment(db, pay) + assertEquals(OutgoingRegistrationResult(id = first.id, initiated = false, new = true), first) + assertEquals( + OutgoingRegistrationResult(id = first.id, initiated = false, new = false), + db.payment.registerOutgoing(pay, null, null) + ) + } + db.checkOutCount(nbIncoming = 6, nbTalerable = 3) + } + + @Test + fun registerBatch() = setup { db, _ -> + // Init batch + val wtid = ShortHashCode.rand() + for (subject in sequenceOf( + "initiated by nexus", + "${ShortHashCode.rand()} https://exchange.com", + "$wtid https://exchange.com", + "$wtid https://exchange.com" + )) { + assertIs<PaymentInitiationResult.Success>( + db.initiated.create(genInitPay(randEbicsId(), subject=subject)) + ) + } + db.initiated.batch(Instant.now(), "BATCH") + + // Register batch + registerOutgoingBatch(db, OutgoingBatch("BATCH", Instant.now())); + db.checkOutCount(nbIncoming = 4, nbTalerable = 2) + } +} + class IncomingPaymentsTest { // Tests creating and bouncing incoming payments in one DB transaction @Test fun bounce() = setup { db, _ -> // creating and bouncing one incoming transaction. val payment = genInPay("incoming and bounced") + val id = randEbicsId() db.payment.registerMalformedIncoming( payment, TalerAmount("KUDOS:2.53"), + id, Instant.now() ).run { assertTrue(new) + assertEquals(id, bounceId) } db.payment.registerMalformedIncoming( payment, TalerAmount("KUDOS:2.53"), + randEbicsId(), Instant.now() ).run { assertFalse(new) + assertEquals(id, bounceId) } db.conn { // Checking one incoming got created @@ -163,39 +213,39 @@ class IncomingPaymentsTest { // Register with missing ID val incoming = genInPay(subject) val incomingMissingId = incoming.copy(bankId = null) - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(1, 0, 1) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(1, 0, 1) assertFalse(db.inTxExists(incoming.bankId!!)) // Idempotent - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(1, 0, 1) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(1, 0, 1) // Different metadata is bounced - ingestIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) - ingestIncomingPayment(db, cfg, genInPay("another $subject")) - db.checkCount(3, 2, 1) + registerIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) + registerIncomingPayment(db, cfg, genInPay("another $subject")) + db.checkInCount(3, 2, 1) // Different medata with missing id is ignored - ingestIncomingPayment(db, cfg, incomingMissingId.copy(amount = TalerAmount("KUDOS:9"))) - ingestIncomingPayment(db, cfg, incomingMissingId.copy(wireTransferSubject = "another $subject")) - db.checkCount(3, 2, 1) + registerIncomingPayment(db, cfg, incomingMissingId.copy(amount = TalerAmount("KUDOS:9"))) + registerIncomingPayment(db, cfg, incomingMissingId.copy(subject = "another $subject")) + db.checkInCount(3, 2, 1) // Recover bank ID when metadata match - ingestIncomingPayment(db, cfg, incoming) + registerIncomingPayment(db, cfg, incoming) assertTrue(db.inTxExists(incoming.bankId!!)) // Idempotent - ingestIncomingPayment(db, cfg, incoming) - db.checkCount(3, 2, 1) + registerIncomingPayment(db, cfg, incoming) + db.checkInCount(3, 2, 1) // Missing ID is ignored - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(3, 2, 1) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(3, 2, 1) // Other ID is bounced known that we know the id - ingestIncomingPayment(db, cfg, incomingMissingId.copy(bankId = "NEW")) - db.checkCount(4, 3, 1) + registerIncomingPayment(db, cfg, incomingMissingId.copy(bankId = "NEW")) + db.checkInCount(4, 3, 1) } // Test creating an incoming kyc taler transaction without and ID and reconcile it later again @@ -207,40 +257,43 @@ class IncomingPaymentsTest { // Register with missing ID val incoming = genInPay(subject) val incomingMissingId = incoming.copy(bankId = null) - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(1, 0, 1) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(1, 0, 1) assertFalse(db.inTxExists(incoming.bankId!!)) // Idempotent - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(1, 0, 1) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(1, 0, 1) // Different metadata is accepted - ingestIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) - ingestIncomingPayment(db, cfg, genInPay("another $subject")) - db.checkCount(3, 0, 3) + registerIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) + registerIncomingPayment(db, cfg, genInPay("another $subject")) + db.checkInCount(3, 0, 3) // Different medata with missing id are accepted - ingestIncomingPayment(db, cfg, incomingMissingId.copy(amount = TalerAmount("KUDOS:9.5"))) - ingestIncomingPayment(db, cfg, incomingMissingId.copy(wireTransferSubject = "again another $subject")) - db.checkCount(5, 0, 5) + registerIncomingPayment(db, cfg, incomingMissingId.copy(amount = TalerAmount("KUDOS:9.5"))) + registerIncomingPayment(db, cfg, incomingMissingId.copy(subject = "again another $subject")) + db.checkInCount(5, 0, 5) // Recover bank ID when metadata match - ingestIncomingPayment(db, cfg, incoming) + registerIncomingPayment(db, cfg, incoming) assertTrue(db.inTxExists(incoming.bankId!!)) // Idempotent - ingestIncomingPayment(db, cfg, incoming) - db.checkCount(5, 0, 5) + registerIncomingPayment(db, cfg, incoming) + db.checkInCount(5, 0, 5) // Missing ID is ignored - ingestIncomingPayment(db, cfg, incomingMissingId) - db.checkCount(5, 0, 5) + registerIncomingPayment(db, cfg, incomingMissingId) + db.checkInCount(5, 0, 5) // Other ID is accepted - ingestIncomingPayment(db, cfg, incomingMissingId.copy(bankId = "NEW")) - db.checkCount(6, 0, 6) + registerIncomingPayment(db, cfg, incomingMissingId.copy(bankId = "NEW")) + db.checkInCount(6, 0, 6) } +} + +class PaymentInitiationsTest { // Test skipping transaction based on config @Test @@ -266,7 +319,7 @@ class IncomingPaymentsTest { genInPay("test at $executionTime", executionTime = executionTime), genOutPay("test at $executionTime", executionTime = executionTime) )) { - ingestTransaction(db, cfg.ebics.ingest, tx) + registerTransaction(db, cfg.ebics.ingest, tx) } } @@ -291,105 +344,232 @@ class IncomingPaymentsTest { ingest(cfg.ebics.fetch.ignoreBouncesBefore.plusMillis(10)) checkCount(10, 2) } -} -class PaymentInitiationsTest { @Test fun status() = setup { db, _ -> - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY1")) - ) - db.initiated.submissionFailure(1, Instant.now(), "First failure") - db.initiated.submissionFailure(1, Instant.now(), "Second failure") - db.initiated.submissionSuccess(1, Instant.now(), "ORDER1") - assertEquals(Pair("PAY1", null), db.initiated.logFailure("ORDER1")) + suspend fun checkPart( + batchId: Long, + batchStatus: SubmissionState, + batchMsg: String?, + txStatus: SubmissionState, + txMsg: String?, + settledStatus: SubmissionState, + settledMsg: String?, + ) { + // Check batch status + val msgId = db.serializable( + """ + SELECT message_id, status, status_msg FROM initiated_outgoing_batches WHERE initiated_outgoing_batch_id=? + """ + ) { + setLong(1, batchId) + one { + val msgId = it.getString("message_id") + assertEquals( + batchStatus to batchMsg, + it.getEnum<SubmissionState>("status") to it.getString("status_msg"), + msgId + ) + msgId + } + } + // Check tx status + db.serializable( + """ + SELECT end_to_end_id, status, status_msg FROM initiated_outgoing_transactions WHERE initiated_outgoing_batch_id=? + """ + ) { + setLong(1, batchId) + all { + val endToEndId = it.getString("end_to_end_id") + val expected = when (endToEndId) { + "TX" -> Pair(txStatus, txMsg) + "TX_SETTLED" -> Pair(settledStatus, settledMsg) + else -> throw Exception("Unexpected tx $endToEndId") + } + assertEquals( + expected, + it.getEnum<SubmissionState>("status") to it.getString("status_msg"), + "$msgId.$endToEndId" + ) + } + } + } + suspend fun checkBatch(batchId: Long, status: SubmissionState, msg: String?, txStatus: SubmissionState? = null) { + val txStatus = txStatus ?: status + checkPart(batchId, status, msg, txStatus, msg, txStatus, msg) + } + suspend fun checkOrder(orderId: String, status: SubmissionState, msg: String?, txStatus: SubmissionState? = null) { + val batchId = db.serializable( + "SELECT initiated_outgoing_batch_id FROM initiated_outgoing_batches WHERE order_id=?" + ) { + setString(1, orderId) + one { + it.getLong("initiated_outgoing_batch_id") + } + } + checkBatch(batchId, status, msg, txStatus) + } - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY2")) - ) - db.initiated.submissionFailure(2, Instant.now(), "First failure") - db.initiated.submissionSuccess(2, Instant.now(), "ORDER2") - db.initiated.logMessage("ORDER2", "status msg") - assertEquals(Pair("PAY2", "status msg"), db.initiated.logFailure("ORDER2")) + suspend fun test(lambda: suspend (Long) -> Unit) { + // Reset DB + db.conn { conn -> + conn.execSQLUpdate("DELETE FROM initiated_outgoing_transactions"); + conn.execSQLUpdate("DELETE FROM initiated_outgoing_batches"); + } + // Create a test batch with three transactions + for (id in sequenceOf("TX", "TX_SETTLED")) { + assertIs<PaymentInitiationResult.Success>( + db.initiated.create(genInitPay(id)) + ) + } + db.initiated.batch(Instant.now(), "BATCH") + // Create witness transactions and batch + for (id in sequenceOf("WITNESS_1", "WITNESS_2")) { + assertIs<PaymentInitiationResult.Success>( + db.initiated.create(genInitPay(id)) + ) + } + db.initiated.batch(Instant.now(), "BATCH_WITNESS") + for (id in sequenceOf("WITNESS_3", "WITNESS_4")) { + assertIs<PaymentInitiationResult.Success>( + db.initiated.create(genInitPay(id)) + ) + } + // Check everything is unsubmitted + db.serializable( + """ + SELECT (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_batches) + AND (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_transactions) + """ + ) { + one { assertTrue(it.getBoolean(1)) } + } + // Run test + lambda(db.initiated.submittable("").find { it.messageId == "BATCH" }!!.id) + // Check witness status is unaltered + db.serializable( + """ + SELECT (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_batches WHERE message_id != 'BATCH') + AND (SELECT bool_and(initiated_outgoing_transactions.status = 'unsubmitted') + FROM initiated_outgoing_transactions JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) + WHERE message_id != 'BATCH') + """ + ) { + one { assertTrue(it.getBoolean(1)) } + } + } - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY3")) - ) - db.initiated.submissionSuccess(3, Instant.now(), "ORDER3") - assertEquals("PAY3", db.initiated.logSuccess("ORDER3")) + // Submission retry status + test { batchId -> + db.initiated.batchSubmissionFailure(batchId, Instant.now(), "First failure") + checkBatch(batchId, SubmissionState.transient_failure, "First failure") + db.initiated.batchSubmissionFailure(batchId, Instant.now(), "Second failure") + checkBatch(batchId, SubmissionState.transient_failure, "Second failure") + db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") + checkOrder("ORDER", SubmissionState.pending, null) + db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") + checkOrder("ORDER", SubmissionState.pending, null) + db.initiated.orderStep("ORDER", "step msg") + checkOrder("ORDER", SubmissionState.pending, "step msg") + db.initiated.orderStep("ORDER", "success msg") + checkOrder("ORDER", SubmissionState.pending, "success msg") + db.initiated.orderSuccess("ORDER") + checkOrder("ORDER", SubmissionState.success, "success msg", SubmissionState.pending) + db.initiated.orderStep("ORDER", "late msg") + checkOrder("ORDER", SubmissionState.success, "success msg", SubmissionState.pending) + } - // Unknown order - assertNull(db.initiated.logSuccess("ORDER_X")) - assertNull(db.initiated.logFailure("ORDER_X")) + // Order step message on failure + test { batchId -> + db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") + checkOrder("ORDER", SubmissionState.pending, null) + db.initiated.orderStep("ORDER", "step msg") + checkOrder("ORDER", SubmissionState.pending, "step msg") + db.initiated.orderStep("ORDER", "failure msg") + checkOrder("ORDER", SubmissionState.pending, "failure msg") + assertEquals("failure msg", db.initiated.orderFailure("ORDER")!!.second) + checkOrder("ORDER", SubmissionState.permanent_failure, "failure msg") + db.initiated.orderStep("ORDER", "late msg") + checkOrder("ORDER", SubmissionState.permanent_failure, "failure msg") + } - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY4")) - ) - db.initiated.bankMessage("PAY4", "status progress") - db.initiated.bankFailure("PAY4", "status failure") + // Payment & batch status + test { batchId -> + checkBatch(batchId, SubmissionState.unsubmitted, null) + db.initiated.batchStatusUpdate("BATCH", StatusUpdate.pending, "progress") + checkBatch(batchId, SubmissionState.pending, "progress") + db.initiated.txStatusUpdate("TX_SETTLED", null, StatusUpdate.success, "success") + checkPart(batchId, SubmissionState.pending, "progress", SubmissionState.pending, "progress", SubmissionState.success, "success") + db.initiated.batchStatusUpdate("BATCH", StatusUpdate.transient_failure, "waiting") + checkPart(batchId, SubmissionState.transient_failure, "waiting", SubmissionState.transient_failure, "waiting", SubmissionState.success, "success") + db.initiated.txStatusUpdate("TX", "BATCH", StatusUpdate.permanent_failure, "failure") + checkPart(batchId, SubmissionState.success, null, SubmissionState.permanent_failure, "failure", SubmissionState.success, "success") + db.initiated.txStatusUpdate("TX_SETTLED", "BATCH", StatusUpdate.permanent_failure, "late") + checkPart(batchId, SubmissionState.success, null, SubmissionState.permanent_failure, "failure", SubmissionState.late_failure, "late") + } - assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY5")) - ) - db.initiated.bankMessage("PAY5", "status progress") - db.initiated.reversal("PAY5", "status reversal") + // Registration + test { batchId -> + checkBatch(batchId, SubmissionState.unsubmitted, null) + registerOutgoingPayment(db, genOutPay("", endToEndId = "TX_SETTLED")) + checkPart(batchId, SubmissionState.unsubmitted, null, SubmissionState.unsubmitted, null, SubmissionState.success, null) + registerOutgoingPayment(db, genOutPay("", endToEndId = "TX", msgId = "BATCH")) + checkPart(batchId, SubmissionState.success, null, SubmissionState.success, null, SubmissionState.success, null) + } + + // Unknown order and batch + db.initiated.batchSubmissionSuccess(42, Instant.now(), "ORDER_X") + db.initiated.batchSubmissionFailure(42, Instant.now(), null) + db.initiated.orderStep("ORDER_X", "msg") + db.initiated.batchStatusUpdate("BATCH_X", StatusUpdate.success, null) + db.initiated.txStatusUpdate("TX_X", "BATCH_X", StatusUpdate.success, "msg") + assertNull(db.initiated.orderSuccess("ORDER_X")) + assertNull(db.initiated.orderFailure("ORDER_X")) } @Test fun submittable() = setup { db, _ -> - for (i in 0..5) { + repeat(6) { assertIs<PaymentInitiationResult.Success>( - db.initiated.create(genInitPay(requestUid = "PAY$i")) + db.initiated.create(genInitPay("PAY$it")) ) + db.initiated.batch(Instant.now(), "BATCH$it") } - assertEquals( - listOf("PAY0", "PAY1", "PAY2", "PAY3", "PAY4", "PAY5"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) + suspend fun checkIds(vararg ids: String) { + assertEquals( + listOf(*ids), + db.initiated.submittable("KUDOS").flatMap { it.payments.map { it.endToEndId } } + ) + } + checkIds("PAY0", "PAY1", "PAY2", "PAY3", "PAY4", "PAY5") // Check submitted not submitable - db.initiated.submissionSuccess(1, Instant.now(), "ORDER1") - assertEquals( - listOf("PAY1", "PAY2", "PAY3", "PAY4", "PAY5"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) + db.initiated.batchSubmissionSuccess(1, Instant.now(), "ORDER1") + checkIds("PAY1", "PAY2", "PAY3", "PAY4", "PAY5") // Check transient failure submitable last - db.initiated.submissionFailure(2, Instant.now(), "Failure") - assertEquals( - listOf("PAY2", "PAY3", "PAY4", "PAY5", "PAY1"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) + db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") + checkIds("PAY2", "PAY3", "PAY4", "PAY5", "PAY1") // Check persistent failure not submitable - db.initiated.bankFailure("PAY3", "status failure") - assertEquals( - listOf("PAY2", "PAY4", "PAY5", "PAY1"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) - db.initiated.reversal("PAY4", "status reversal") - assertEquals( - listOf("PAY2", "PAY5", "PAY1"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) + db.initiated.batchSubmissionSuccess(4, Instant.now(), "ORDER3") + db.initiated.orderFailure("ORDER3") + checkIds("PAY2", "PAY4", "PAY5", "PAY1") + db.initiated.batchSubmissionSuccess(5, Instant.now(), "ORDER4") + db.initiated.orderFailure("ORDER4") + checkIds("PAY2", "PAY5", "PAY1") // Check rotation - db.initiated.submissionFailure(3, Instant.now(), "Failure") - assertEquals( - listOf("PAY5", "PAY1", "PAY2"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) - db.initiated.submissionFailure(6, Instant.now(), "Failure") - assertEquals( - listOf("PAY1", "PAY2", "PAY5"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) - db.initiated.submissionFailure(2, Instant.now(), "Failure") - assertEquals( - listOf("PAY2", "PAY5", "PAY1"), - db.initiated.submittable("KUDOS").map { it.requestUid } - ) + db.initiated.batchSubmissionFailure(3, Instant.now(), "Failure") + checkIds("PAY5", "PAY1", "PAY2") + db.initiated.batchSubmissionFailure(6, Instant.now(), "Failure") + checkIds("PAY1", "PAY2", "PAY5") + db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") + checkIds("PAY2", "PAY5", "PAY1") } + + // TODO test for unsettledTxInBatch } class EbicsTxTest { diff --git a/nexus/src/test/kotlin/Iso20022Test.kt b/nexus/src/test/kotlin/Iso20022Test.kt @@ -18,160 +18,374 @@ */ import org.junit.Test -import tech.libeufin.common.TalerAmount -import tech.libeufin.common.dateToInstant -import tech.libeufin.nexus.IncomingPayment -import tech.libeufin.nexus.OutgoingPayment -import tech.libeufin.nexus.TxNotification.Reversal -import tech.libeufin.nexus.ebics.Dialect -import tech.libeufin.nexus.parseTx -import java.nio.file.Files -import kotlin.io.path.Path -import kotlin.test.assertEquals +import tech.libeufin.common.* +import tech.libeufin.nexus.* +import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* +import kotlin.io.path.* +import kotlin.test.* +import java.time.Instant class Iso20022Test { @Test + fun pain001() { + val creditor = IbanAccountMetadata( + iban = "CH4189144589712575493", + bic = null, + name = "Test" + ) + val msg = Pain001Msg( + messageId = "MESSAGE_ID", + timestamp = dateToInstant("2024-09-09"), + debtor = IbanAccountMetadata( + iban = "CH7789144474425692816", + bic = "BIC", + name = "myname" + ), + sum = TalerAmount("EUR:47.32"), + txs = listOf( + Pain001Tx( + creditor = creditor, + amount = TalerAmount("EUR:42"), + subject = "Test 42", + endToEndId = "TX_FIRST" + ), + Pain001Tx( + creditor = creditor, + amount = TalerAmount("EUR:5.11"), + subject = "Test 5.11", + endToEndId = "TX_SECOND" + ), + Pain001Tx( + creditor = creditor, + amount = TalerAmount("EUR:0.21"), + subject = "Test 0.21", + endToEndId = "TX_THIRD" + ) + ) + ) + for (dialect in Dialect.entries) { + assertContentEquals( + Path("sample/platform/${dialect}_pain001.xml").readBytes(), + createPain001(msg, dialect) + ) + } + } + + @Test + fun hac() { + assertContentEquals( + parseCustomerAck(Path("sample/platform/hac.xml").inputStream()), + listOf( + CustomerAck( + actionType = HacAction.FILE_DOWNLOAD, + orderId = null, + code = ExternalStatusReasonCode.TS01, + info = "", + timestamp = dateTimeToInstant("2024-09-02T15:47:30.350Z") + ), + CustomerAck( + actionType = HacAction.FILE_UPLOAD, + orderId = "ORDER_SUCCESS", + code = ExternalStatusReasonCode.TS01, + info = "", + timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") + ), + CustomerAck( + actionType = HacAction.ES_VERIFICATION, + orderId = "ORDER_SUCCESS", + code = ExternalStatusReasonCode.DS01, + info = "", + timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") + ), + CustomerAck( + actionType = HacAction.ORDER_HAC_FINAL_POS, + orderId = "ORDER_SUCCESS", + code = null, + info = "Some multiline info", + timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") + ), + CustomerAck( + actionType = HacAction.FILE_DOWNLOAD, + orderId = null, + code = ExternalStatusReasonCode.TD01, + info = "", + timestamp = dateTimeToInstant("2024-09-02T15:47:31.754Z") + ), + CustomerAck( + actionType = HacAction.FILE_UPLOAD, + orderId = "ORDER_FAILURE", + code = ExternalStatusReasonCode.TS01, + info = "", + timestamp = dateTimeToInstant("2024-08-23T15:34:11.987") + ), + CustomerAck( + actionType = HacAction.ES_VERIFICATION, + orderId = "ORDER_FAILURE", + code = ExternalStatusReasonCode.TD03, + info = "", + timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") + ), + CustomerAck( + actionType = HacAction.ORDER_HAC_FINAL_NEG, + orderId = "ORDER_FAILURE", + code = null, + info = "", + timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") + ), + ) + ) + } + + @Test fun postfinance_camt054() { - val content = Files.newInputStream(Path("sample/platform/postfinance_camt054.xml")) - val txs = parseTx(content, "CHF", Dialect.postfinance) - assertEquals( + assertContentEquals( + parseTx(Path("sample/platform/postfinance_camt054.xml").inputStream(), "CHF", Dialect.postfinance), listOf( OutgoingPayment( - messageId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", + endToEndId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", + msgId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", amount = TalerAmount("CHF:3.00"), - wireTransferSubject = null, + subject = null, executionTime = dateToInstant("2024-01-15"), - creditPaytoUri = null + creditorPayto = null ), IncomingPayment( bankId = "62e2b511-7313-4ccd-8d40-c9d8e612cd71", amount = TalerAmount("CHF:10"), - wireTransferSubject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YBG", + subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YBG", executionTime = dateToInstant("2023-12-19"), - debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr%20Test" + debtorPayto = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( bankId = "62e2b511-7313-4ccd-8d40-c9d8e612cd71", amount = TalerAmount("CHF:2.53"), - wireTransferSubject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YB", + subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YB", executionTime = dateToInstant("2023-12-19"), - debitPaytoUri = "payto://iban/CH7389144832588726658?receiver-name=Mr%20Test" + debtorPayto = ibanPayto("CH7389144832588726658", "Mr Test") + ), + OutgoingBatch( + msgId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", + executionTime = dateToInstant("2024-01-15") ) - ), - txs + ) ) } @Test fun postfinance_camt053() { - val content = Files.newInputStream(Path("sample/platform/postfinance_camt053.xml")) - val txs = parseTx(content, "CHF", Dialect.postfinance) - assertEquals( + assertContentEquals( + parseTx(Path("sample/platform/postfinance_camt053.xml").inputStream(), "CHF", Dialect.postfinance), listOf( - Reversal( + OutgoingReversal( + endToEndId = "889d1a80-1267-49bd-8fcc-85701a", msgId = "889d1a80-1267-49bd-8fcc-85701a", reason = "InconsistenWithEndCustomer 'Identification of end customer is not consistent with associated account number, organisation ID or private ID.' - 'more info here ...'", executionTime = dateToInstant("2023-11-22") ), - Reversal( + OutgoingReversal( + endToEndId = "4cc61cc7-6230-49c2-b5e2-b40bbb", msgId = "4cc61cc7-6230-49c2-b5e2-b40bbb", reason = "MissingCreditorNameOrAddress 'Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing.' - 'more info here ...'", executionTime = dateToInstant("2023-11-22") ) - ), - txs + ) ) } @Test fun gls_camt052() { - val content = Files.newInputStream(Path("sample/platform/gls_camt052.xml")) - val txs = parseTx(content, "EUR", Dialect.gls) - assertEquals( + assertContentEquals( + parseTx(Path("sample/platform/gls_camt052.xml").inputStream(), "EUR", Dialect.gls), listOf( OutgoingPayment( - messageId = "G059N0SR5V0WZ0XSFY1H92QBZ0", + endToEndId = "COMPAT_SUCCESS", + msgId = "COMPAT_SUCCESS", amount = TalerAmount("EUR:2"), - wireTransferSubject = "TestABC123", + subject = "TestABC123", executionTime = dateToInstant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") ), - OutgoingPayment( - messageId = "YF5QBARGQ0MNY0VK59S477VDG4", - amount = TalerAmount("EUR:1.1"), - wireTransferSubject = "This should fail because dummy", - executionTime = dateToInstant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" + OutgoingReversal( + endToEndId = "8XK8Z7RAX224FGWK832FD40GYC", + reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", + executionTime = dateToInstant("2024-09-05") ), IncomingPayment( bankId = "BYLADEM1WOR-G2910276709458A2", amount = TalerAmount("EUR:3"), - wireTransferSubject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", + subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = dateToInstant("2024-04-12"), - debitPaytoUri = "payto://iban/DE84500105177118117964?receiver-name=John%20Smith" + debtorPayto = ibanPayto("DE84500105177118117964", "John Smith") ), - Reversal( - msgId = "G27KNKZAR5DV7HRB085YMA9GB4", + OutgoingReversal( + endToEndId = "COMPAT_FAILURE", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", executionTime = dateToInstant("2024-04-12") - ) - ), - txs + ), + OutgoingPayment( + endToEndId = "FD622SMXKT5QWSAHDY0H8NYG3G", + msgId = "BATCH_SINGLE_SUCCESS", + amount = TalerAmount("EUR:1.1"), + subject = "single 2024-09-02T14:29:52.875253314Z", + executionTime = dateToInstant("2024-09-02"), + creditorPayto = ibanPayto("DE89500105173198527518", "Grothoff Hans") + ), + OutgoingPayment( + endToEndId = "YF5QBARGQ0MNY0VK59S477VDG4", + msgId = "YF5QBARGQ0MNY0VK59S477VDG4", + amount = TalerAmount("EUR:1.1"), + subject = "Simple tx", + executionTime = dateToInstant("2024-04-18"), + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") + ), + OutgoingBatch( + msgId = "BATCH_MANY_SUCCESS", + executionTime = dateToInstant("2024-09-20"), + ), + OutgoingPayment( + endToEndId = "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", + msgId = "BATCH_SINGLE_RETURN", + amount = TalerAmount("EUR:0.42"), + subject = "This should fail because bad iban", + executionTime = dateToInstant("2024-09-23"), + creditorPayto = ibanPayto("DE18500105173385245163", "John Smith") + ), + OutgoingReversal( + endToEndId = "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", + reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", + executionTime = dateToInstant("2024-09-24") + ), + ) ) } @Test fun gls_camt053() { - val content = Files.newInputStream(Path("sample/platform/gls_camt053.xml")) - val txs = parseTx(content, "EUR", Dialect.gls) - assertEquals( + assertContentEquals( + parseTx(Path("sample/platform/gls_camt053.xml").inputStream(), "EUR", Dialect.gls), listOf( OutgoingPayment( - messageId = "G059N0SR5V0WZ0XSFY1H92QBZ0", + endToEndId = "COMPAT_SUCCESS", + msgId = "COMPAT_SUCCESS", amount = TalerAmount("EUR:2"), - wireTransferSubject = "TestABC123", + subject = "TestABC123", executionTime = dateToInstant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") ), - OutgoingPayment( - messageId = "YF5QBARGQ0MNY0VK59S477VDG4", - amount = TalerAmount("EUR:1.1"), - wireTransferSubject = "This should fail because dummy", - executionTime = dateToInstant("2024-04-18"), - creditPaytoUri = "payto://iban/DE20500105172419259181?receiver-name=John%20Smith" + OutgoingReversal( + endToEndId = "KGTDBASWTJ6JM89WXD3Q5KFQC4", + reason = "Retoure aus SEPA Überweisung multi line", + executionTime = dateToInstant("2024-09-04") + ), + OutgoingBatch( + msgId = "BATCH_MANY_PART", + executionTime = dateToInstant("2024-09-04") ), IncomingPayment( bankId = "BYLADEM1WOR-G2910276709458A2", amount = TalerAmount("EUR:3"), - wireTransferSubject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", + subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = dateToInstant("2024-04-12"), - debitPaytoUri = "payto://iban/DE84500105177118117964?receiver-name=John%20Smith" + debtorPayto = ibanPayto("DE84500105177118117964", "John Smith") ), - Reversal( - msgId = "G27KNKZAR5DV7HRB085YMA9GB4", + OutgoingReversal( + endToEndId = "COMPAT_FAILURE", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", executionTime = dateToInstant("2024-04-12") - ) - ), - txs + ), + OutgoingPayment( + endToEndId = "FD622SMXKT5QWSAHDY0H8NYG3G", + msgId = "BATCH_SINGLE_SUCCESS", + amount = TalerAmount("EUR:1.1"), + subject = "single 2024-09-02T14:29:52.875253314Z", + executionTime = dateToInstant("2024-09-02"), + creditorPayto = ibanPayto("DE89500105173198527518", "Grothoff Hans") + ), + OutgoingPayment( + endToEndId = "YF5QBARGQ0MNY0VK59S477VDG4", + msgId = "YF5QBARGQ0MNY0VK59S477VDG4", + amount = TalerAmount("EUR:1.1"), + subject = "Simple tx", + executionTime = dateToInstant("2024-04-18"), + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") + ), + ) ) } @Test fun gls_camt054() { - val content = Files.newInputStream(Path("sample/platform/gls_camt054.xml")) - val txs = parseTx(content, "EUR", Dialect.gls) - assertEquals( + assertContentEquals( + parseTx(Path("sample/platform/gls_camt054.xml").inputStream(), "EUR", Dialect.gls), listOf( IncomingPayment( bankId = null, //"IS11PGENODEFF2DA8899900378806", amount = TalerAmount("EUR:2.5"), - wireTransferSubject = "Test ICT", + subject = "Test ICT", executionTime = dateToInstant("2024-05-05"), - debitPaytoUri = "payto://iban/DE84500105177118117964?receiver-name=Mr%20Test" + debtorPayto = ibanPayto("DE84500105177118117964", "Mr Test") ) - ), - txs + ) + ) + } + + @Test + fun pain002() { + assertEquals( + parseCustomerPaymentStatusReport(Path("sample/platform/pain002.xml").inputStream()), + MsgStatus( + id = "05BD4C5B4A2649B5B08F6EF6A31F197A", + code = ExternalPaymentGroupStatusCode.PART, + reasons = emptyList(), + payments = listOf( + PmtStatus( + id = "NOTPROVIDED", + code = ExternalPaymentGroupStatusCode.PART, + reasons = listOf( + Reason( + code = ExternalStatusReasonCode.DT06, + information = "Due date is not a working day. Order will be executed on the next working day" + ) + ), + transactions = listOf( + TxStatus( + id = "AQCXNCPWD8PHW5JTN65Y5XTF7R", + endToEndId = "AQCXNCPWD8PHW5JTN65Y5XTF7R", + code = ExternalPaymentTransactionStatusCode.RJCT, + reasons = listOf( + Reason( + code = ExternalStatusReasonCode.AC04, + information = "Error message" + ) + ) + ), + TxStatus( + id = "EE9SX76FC5YSC657EK3GMVZ9TC", + endToEndId = "EE9SX76FC5YSC657EK3GMVZ9TC", + code = ExternalPaymentTransactionStatusCode.RJCT, + reasons = listOf( + Reason( + code = ExternalStatusReasonCode.MS03, + information = "Error message" + ) + ) + ), + TxStatus( + id = "V5B3MXPEWES9VQW1JDRD6VAET4", + endToEndId = "V5B3MXPEWES9VQW1JDRD6VAET4", + code = ExternalPaymentTransactionStatusCode.RJCT, + reasons = listOf( + Reason( + code = ExternalStatusReasonCode.RR02, + information = "Error message" + ) + ) + ) + ) + ) + ) + ) ) } } \ No newline at end of file diff --git a/nexus/src/test/kotlin/RegistrationTest.kt b/nexus/src/test/kotlin/RegistrationTest.kt @@ -0,0 +1,401 @@ +/* + * This file is part of LibEuFin. + * Copyright (C) 2024 Taler Systems S.A. + + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ + +import org.junit.Test +import tech.libeufin.common.* +import tech.libeufin.common.db.* +import tech.libeufin.nexus.* +import tech.libeufin.nexus.cli.* +import tech.libeufin.nexus.db.* +import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* +import java.nio.file.Files +import java.time.Instant +import kotlin.io.path.* +import kotlin.test.* + +/** End-to-end test for XML file registration */ +class RegistrationTest { + + /** Register batches of initiated payments for reconcciliation */ + suspend fun Database.batches(batches: Map<String, List<InitiatedPayment>>): List<PaymentBatch> { + val tmp = mutableListOf<PaymentBatch>() + for ((name, txs) in batches) { + for (tx in txs) { + initiated.create(tx) + } + this.initiated.batch(Instant.now(), name) + val (batch) = this.initiated.submittable("EUR") + this.initiated.batchSubmissionSuccess(batch.id, Instant.now(), name.replace("BATCH", "ORDER")) + tmp.add(batch) + } + return tmp + } + + /** Register an XML sample into the database */ + suspend fun Database.register( + cfg: NexusEbicsConfig, + path: String, + doc: OrderDoc + ) { + registerFile(this, cfg, Files.newInputStream(Path(path)), doc) + } + + /** Check database content */ + suspend fun Database.check( + status: Map<String, Pair<SubmissionState, Map<String, SubmissionState>>>, + incoming: List<IncomingPayment>, + outgoing: List<OutgoingPayment> + ) { + // Check batch status + val batch_status = this.serializable( + """ + SELECT message_id, status FROM initiated_outgoing_batches ORDER BY initiated_outgoing_batch_id + """ + ) { + all { + Pair( + it.getString("message_id"), + it.getEnum<SubmissionState>("status") + ) + } + } + assertContentEquals(status.map { Pair(it.key, it.value.first) }, batch_status) + + // Check transactions status + val batch_tx = this.serializable( + """ + SELECT message_id, end_to_end_id, initiated_outgoing_transactions.status + FROM initiated_outgoing_transactions + JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) + ORDER BY initiated_outgoing_batch_id, initiated_outgoing_transaction_id + """ + ) { + all { + Triple( + it.getString("message_id"), + it.getString("end_to_end_id"), + it.getEnum<SubmissionState>("status") + ) + }.groupBy( + keySelector = { it.first }, + valueTransform = { Pair(it.second, it.third) } + ).mapValues { it.value.toMap() } + } + assertContentEquals(status.mapValues { it.value.second }.toList(), batch_tx.toList()) + + // Check incoming transactions + val incoming_tx = this.serializable( + """ + SELECT bank_id + ,(amount).val as amount_val + ,(amount).frac AS amount_frac + ,subject + ,execution_time + ,debit_payto + FROM incoming_transactions + ORDER BY incoming_transaction_id + """ + ) { + all { + IncomingPayment( + bankId = it.getString("bank_id"), + amount = it.getAmount("amount", this@check.bankCurrency), + subject = it.getString("subject"), + executionTime = it.getLong("execution_time").asInstant(), + debtorPayto = it.getIbanPayto("debit_payto"), + ) + } + } + assertContentEquals(incoming, incoming_tx) + + // Check outgoing transactions + val outgoing_tx = this.serializable( + """ + SELECT end_to_end_id + ,(amount).val as amount_val + ,(amount).frac AS amount_frac + ,subject + ,execution_time + ,credit_payto + FROM outgoing_transactions + ORDER BY outgoing_transaction_id + """ + ) { + all { + OutgoingPayment( + endToEndId = it.getString("end_to_end_id"), + amount = it.getAmount("amount", this@check.bankCurrency), + subject = it.getString("subject"), + executionTime = it.getLong("execution_time").asInstant(), + creditorPayto = it.getIbanPayto("credit_payto"), + ) + } + } + assertContentEquals(outgoing, outgoing_tx) + } + + @Test + fun pain001() = setup { db, cfg -> + val (batch) = db.batches(mapOf( + "MESSAGE_ID" to listOf( + genInitPay( + endToEndId = "TX_FIRST", + amount = "EUR:42", + subject = "Test 42", + ), + genInitPay( + endToEndId = "TX_SECOND", + amount = "EUR:5.11", + subject = "Test 5.11", + ), + genInitPay( + endToEndId = "TX_THIRD", + amount = "EUR:0.21", + subject = "Test 0.21", + ), + ), + )) + val msg = batchToPain001Msg(cfg.ebics.account, batch).copy(timestamp = dateToInstant("2024-09-09"),) + for (dialect in Dialect.entries) { + assertContentEquals( + Path("sample/platform/${dialect}_pain001.xml").readBytes(), + createPain001(msg, dialect) + ) + } + } + + /** HAC order id test */ + @Test + fun hac() = setup { db, cfg -> + db.batches(mapOf( + "BATCH_SUCCESS" to listOf( + genInitPay("BATCH_SUCCESS_0"), + genInitPay("BATCH_SUCCESS_1"), + ), + "BATCH_FAILURE" to listOf( + genInitPay("BATCH_FAILURE_0"), + genInitPay("BATCH_FAILURE_1"), + ) + )) + + // Register HAC files + db.register(cfg.ebics, "sample/platform/hac.xml", OrderDoc.acknowledgement) + + // Check state + db.check( + status = mapOf( + "BATCH_SUCCESS" to Pair(SubmissionState.success, mapOf( + "BATCH_SUCCESS_0" to SubmissionState.pending, + "BATCH_SUCCESS_1" to SubmissionState.pending, + )), + "BATCH_FAILURE" to Pair(SubmissionState.permanent_failure, mapOf( + "BATCH_FAILURE_0" to SubmissionState.permanent_failure, + "BATCH_FAILURE_1" to SubmissionState.permanent_failure, + )) + ), + incoming = emptyList(), + outgoing = emptyList() + ) + } + + /** CreditSuisse dialect test */ + @Test + fun cs() = setup { db, cfg -> + db.batches(mapOf( + "05BD4C5B4A2649B5B08F6EF6A31F197A" to listOf( + genInitPay("AQCXNCPWD8PHW5JTN65Y5XTF7R"), + genInitPay("EE9SX76FC5YSC657EK3GMVZ9TC"), + genInitPay("V5B3MXPEWES9VQW1JDRD6VAET4"), + genInitPay("M9NGRCAC1FBX3ENX3XEDEPJ2JW"), + ), + )) + + // Register pain files + db.register(cfg.ebics, "sample/platform/pain002.xml", OrderDoc.status) + + // Check state + db.check( + status = mapOf( + "05BD4C5B4A2649B5B08F6EF6A31F197A" to Pair(SubmissionState.pending, mapOf( + "AQCXNCPWD8PHW5JTN65Y5XTF7R" to SubmissionState.permanent_failure, + "EE9SX76FC5YSC657EK3GMVZ9TC" to SubmissionState.permanent_failure, + "V5B3MXPEWES9VQW1JDRD6VAET4" to SubmissionState.permanent_failure, + "M9NGRCAC1FBX3ENX3XEDEPJ2JW" to SubmissionState.pending, + )), + ), + incoming = emptyList(), + outgoing = emptyList() + ) + } + + /** GLS dialect test */ + @Test + fun gls() = setup("gls.conf") { db, cfg -> + db.batches(mapOf( + "COMPAT_SUCCESS" to listOf( + genInitPay("COMPAT_SUCCESS") + ), + "COMPAT_FAILURE" to listOf( + genInitPay("COMPAT_FAILURE") + ), + "BATCH_SINGLE_SUCCESS" to listOf( + genInitPay("FD622SMXKT5QWSAHDY0H8NYG3G"), + ), + // JEYMR3OYZTFM7505OWWENFPAH53LNOWJHS + "BATCH_SINGLE_FAILURE" to listOf( + genInitPay("DAFC3NEE4T48WVC560T76ABA2C"), + ), + "BATCH_SINGLE_RETURN" to listOf( + genInitPay("KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5"), + ), + "BATCH_MANY_SUCCESS" to listOf( + genInitPay("IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V"), + genInitPay("CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW"), + genInitPay("35M1268GW5ZFHS5JCB41UKDQNPMD40T849"), + genInitPay("HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1"), + ), + "BATCH_MANY_PART" to listOf( + genInitPay("27SK3166EG36SJ7VP7VFYP0MW8"), + genInitPay("KGTDBASWTJ6JM89WXD3Q5KFQC4"), + genInitPay("8XK8Z7RAX224FGWK832FD40GYC"), + ), + // ZQOOPJC1DYBP52X119YGO6WMXU6NWIDPJK + "BATCH_MANY_FAILURE" to listOf( + genInitPay("4XTPKWE4A9V90PRQJCT8Z3MQZ8"), + genInitPay("3VZZHVYJ6XP2SNPKWF4D4YVHNG"), + ) + )) + + // Register camt files + db.register(cfg.ebics, "sample/platform/gls_camt052.xml", OrderDoc.report) + db.register(cfg.ebics, "sample/platform/gls_camt053.xml", OrderDoc.statement) + // TODO camt054 with missing id before and after + + // Check state + db.check( + status = mapOf( + "COMPAT_SUCCESS" to Pair(SubmissionState.success, mapOf( + "COMPAT_SUCCESS" to SubmissionState.success + )), + "COMPAT_FAILURE" to Pair(SubmissionState.pending, mapOf( + "COMPAT_FAILURE" to SubmissionState.permanent_failure + )), + "BATCH_SINGLE_SUCCESS" to Pair(SubmissionState.success, mapOf( + "FD622SMXKT5QWSAHDY0H8NYG3G" to SubmissionState.success + )), + "BATCH_SINGLE_FAILURE" to Pair(SubmissionState.pending, mapOf( // TODO success + "DAFC3NEE4T48WVC560T76ABA2C" to SubmissionState.pending, // TODO failure + )), + "BATCH_SINGLE_RETURN" to Pair(SubmissionState.success, mapOf( + "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5" to SubmissionState.late_failure, + )), + "BATCH_MANY_SUCCESS" to Pair(SubmissionState.success, mapOf( + "IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V" to SubmissionState.success, + "CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW" to SubmissionState.success, + "35M1268GW5ZFHS5JCB41UKDQNPMD40T849" to SubmissionState.success, + "HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1" to SubmissionState.success, + )), + "BATCH_MANY_PART" to Pair(SubmissionState.success, mapOf( + "27SK3166EG36SJ7VP7VFYP0MW8" to SubmissionState.success, + "KGTDBASWTJ6JM89WXD3Q5KFQC4" to SubmissionState.permanent_failure, + "8XK8Z7RAX224FGWK832FD40GYC" to SubmissionState.permanent_failure, + )), + "BATCH_MANY_FAILURE" to Pair(SubmissionState.pending, mapOf( // TODO success + "4XTPKWE4A9V90PRQJCT8Z3MQZ8" to SubmissionState.pending, // TODO failure + "3VZZHVYJ6XP2SNPKWF4D4YVHNG" to SubmissionState.pending, // TODO failure + )) + ), + incoming = listOf( + IncomingPayment( + bankId = "BYLADEM1WOR-G2910276709458A2", + amount = TalerAmount("EUR:3"), + subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", + executionTime = dateToInstant("2024-04-12"), + debtorPayto = ibanPayto("DE84500105177118117964", "John Smith") + ), + ), + outgoing = listOf( + OutgoingPayment( + endToEndId = "COMPAT_SUCCESS", + amount = TalerAmount("EUR:2"), + subject = "TestABC123", + executionTime = dateToInstant("2024-04-18"), + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") + ), + OutgoingPayment( + endToEndId = "FD622SMXKT5QWSAHDY0H8NYG3G", + amount = TalerAmount("EUR:1.1"), + subject = "single 2024-09-02T14:29:52.875253314Z", + executionTime = dateToInstant("2024-09-02"), + creditorPayto = ibanPayto("DE89500105173198527518", "Grothoff Hans") + ), + OutgoingPayment( + endToEndId = "YF5QBARGQ0MNY0VK59S477VDG4", + amount = TalerAmount("EUR:1.1"), + subject = "Simple tx", + executionTime = dateToInstant("2024-04-18"), + creditorPayto = ibanPayto("DE20500105172419259181", "John Smith") + ), + OutgoingPayment( + endToEndId = "IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V", + amount = TalerAmount("EUR:44"), + subject = "init payment", + executionTime = dateToInstant("2024-09-20"), + creditorPayto = ibanPayto("CH4189144589712575493", "Test") + ), + OutgoingPayment( + endToEndId = "CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW", + amount = TalerAmount("EUR:44"), + subject = "init payment", + executionTime = dateToInstant("2024-09-20"), + creditorPayto = ibanPayto("CH4189144589712575493", "Test") + ), + OutgoingPayment( + endToEndId = "35M1268GW5ZFHS5JCB41UKDQNPMD40T849", + amount = TalerAmount("EUR:44"), + subject = "init payment", + executionTime = dateToInstant("2024-09-20"), + creditorPayto = ibanPayto("CH4189144589712575493", "Test") + ), + OutgoingPayment( + endToEndId = "HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1", + amount = TalerAmount("EUR:44"), + subject = "init payment", + executionTime = dateToInstant("2024-09-20"), + creditorPayto = ibanPayto("CH4189144589712575493", "Test") + ), + OutgoingPayment( + endToEndId = "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", + amount = TalerAmount("EUR:0.42"), + subject = "This should fail because bad iban", + executionTime = dateToInstant("2024-09-23"), + creditorPayto = ibanPayto("DE18500105173385245163", "John Smith") + ), + OutgoingPayment( + endToEndId = "27SK3166EG36SJ7VP7VFYP0MW8", + amount = TalerAmount("EUR:44"), + subject = "init payment", + executionTime = dateToInstant("2024-09-04"), + creditorPayto = ibanPayto("CH4189144589712575493", "Test") + ), + ) + ) + } +} +\ No newline at end of file diff --git a/nexus/src/test/kotlin/RevenueApiTest.kt b/nexus/src/test/kotlin/RevenueApiTest.kt @@ -47,7 +47,7 @@ class RevenueApiTest { }, { // Common credit transactions - ingestIn(db) + registerIn(db) } ), ignored = listOf( diff --git a/nexus/src/test/kotlin/WireGatewayApiTest.kt b/nexus/src/test/kotlin/WireGatewayApiTest.kt @@ -22,9 +22,10 @@ import io.ktor.http.* import io.ktor.server.testing.* import org.junit.Test import tech.libeufin.common.* -import tech.libeufin.nexus.cli.ingestOutgoingPayment -import kotlin.test.* +import tech.libeufin.nexus.cli.registerOutgoingPayment +import tech.libeufin.nexus.ebics.randEbicsId import java.time.Instant +import kotlin.test.* class WireGatewayApiTest { // GET /taler-wire-gateway/config @@ -159,6 +160,7 @@ class WireGatewayApiTest { "credit_account" to grothoffPayto } }.assertOkJson<TransferResponse>() + db.initiated.batch(Instant.now(), randEbicsId()) } client.getA("/taler-wire-gateway/transfers") .assertOkJson<TransferList> { @@ -170,17 +172,14 @@ class WireGatewayApiTest { } client.getA("/taler-wire-gateway/transfers?status=success").assertNoContent() - db.initiated.submissionSuccess(1, Instant.now(), "ORDER1") - db.initiated.submissionFailure(2, Instant.now(), "Failure") - db.initiated.submissionFailure(3, Instant.now(), "Failure") - client.getA("/taler-wire-gateway/transfers?status=success").assertOkJson<TransferList> { - assertEquals(1, it.transfers.size) - } + db.initiated.batchSubmissionSuccess(1, Instant.now(), "ORDER1") + db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") + db.initiated.batchSubmissionFailure(3, Instant.now(), "Failure") client.getA("/taler-wire-gateway/transfers?status=transient_failure").assertOkJson<TransferList> { assertEquals(2, it.transfers.size) } client.getA("/taler-wire-gateway/transfers?status=pending").assertOkJson<TransferList> { - assertEquals(3, it.transfers.size) + assertEquals(4, it.transfers.size) } } @@ -206,7 +205,7 @@ class WireGatewayApiTest { ), ignored = listOf( // Ignore malformed incoming transaction - { ingestIn(db) }, + { registerIn(db) }, // Ignore outgoing transaction { talerableOut(db) }, @@ -233,10 +232,10 @@ class WireGatewayApiTest { { talerableIn(db) }, // Ignore malformed incoming transaction - { ingestIn(db) }, + { registerIn(db) }, // Ignore malformed outgoing transaction - { ingestOutgoingPayment(db, genOutPay("ignored")) }, + { registerOutgoingPayment(db, genOutPay("ignored")) }, ) ) } @@ -319,7 +318,6 @@ class WireGatewayApiTest { talerableKycIn(db, amount = "CHF:4") client.getA("/taler-wire-gateway/history/incoming?limit=25").assertOkJson<IncomingHistory> { assertEquals(4, it.incoming_transactions.size) - println(it) it.incoming_transactions.forEachIndexed { i, tx -> assertEquals(TalerAmount("CHF:${i+1}"), tx.amount) if (i % 2 == 1) { diff --git a/nexus/src/test/kotlin/bench.kt b/nexus/src/test/kotlin/bench.kt @@ -17,25 +17,13 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.request.* -import io.ktor.http.* import org.junit.Test import org.postgresql.jdbc.PgConnection -import tech.libeufin.nexus.* -import tech.libeufin.nexus.cli.* import tech.libeufin.common.* import tech.libeufin.common.test.* -import tech.libeufin.common.crypto.PwCrypto -import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneId -import java.util.* +import tech.libeufin.nexus.* +import tech.libeufin.nexus.cli.* import kotlin.math.max -import kotlin.math.pow -import kotlin.math.sqrt -import kotlin.time.DurationUnit -import kotlin.time.measureTime -import kotlin.time.toDuration class Bench { @@ -46,17 +34,17 @@ class Bench { val token64 = ByteArray(64) conn.genData(amount, sequenceOf( - "incoming_transactions(amount, wire_transfer_subject, execution_time, debit_payto_uri, bank_id)" to { + "incoming_transactions(amount, subject, execution_time, debit_payto, bank_id)" to { "(42,0)\tsubject\t0\tdebit_payto\tBANK_ID${it*2}\n" + "(42,0)\tsubject\t0\tdebit_payto\tBANK_ID${it*2+1}\n" + "(42,0)\tsubject\t0\tdebit_payto\t\\N\n" }, - "outgoing_transactions(amount, wire_transfer_subject, execution_time, credit_payto_uri, message_id)" to { - "(42,0)\tsubject\t0\tcredit_payto\tMSG_ID${it*2}\n" + - "(42,0)\tsubject\t0\tcredit_payto\tMSG_ID${it*2+1}\n" + "outgoing_transactions(amount, subject, execution_time, credit_payto, end_to_end_id)" to { + "(42,0)\tsubject\t0\tcredit_payto\tE2E_ID${it*2}\n" + + "(42,0)\tsubject\t0\tcredit_payto\tE2E_ID${it*2+1}\n" }, - "initiated_outgoing_transactions(amount, wire_transfer_subject, initiation_time, credit_payto_uri, outgoing_transaction_id, request_uid, order_id)" to { - "(42,0)\tsubject\t0\tcredit_payto\t${it*2}\tREQUEST_UID$it\tORDER_ID$it\n" + "initiated_outgoing_transactions(amount, subject, initiation_time, credit_payto, outgoing_transaction_id, end_to_end_id)" to { + "(42,0)\tsubject\t0\tcredit_payto\t${it*2}\tE2E_ID$it\n" }, "talerable_incoming_transactions(type, reserve_public_key, account_pub, incoming_transaction_id)" to { val hex = token32.rand().encodeHex() @@ -98,28 +86,28 @@ class Bench { // Warm HTTP client client.getA("/taler-revenue/config").assertOk() - // Ingest - measureAction("ingest_in") { - ingestIn(db) + // Register + measureAction("register_in") { + registerIn(db) } - measureAction("ingest_out") { - ingestOut(db) + measureAction("register_out") { + registerOut(db) } - measureAction("ingest_reserve") { + measureAction("register_reserve") { talerableIn(db) } - measureAction("ingest_kyc") { + measureAction("register_kyc") { talerableKycIn(db) } - measureAction("ingest_reserve_missing_id") { + measureAction("register_reserve_missing_id") { val incoming = genInPay("test with ${ShortHashCode.rand()} reserve pub") - ingestIncomingPayment(db, ingestCfg, incoming.copy(bankId = null)) - ingestIncomingPayment(db, ingestCfg, incoming) + registerIncomingPayment(db, ingestCfg, incoming.copy(bankId = null)) + registerIncomingPayment(db, ingestCfg, incoming) } - measureAction("ingest_kyc_missing_id") { + measureAction("register_kyc_missing_id") { val incoming = genInPay("test with KYC:${ShortHashCode.rand()} account pub") - ingestIncomingPayment(db, ingestCfg, incoming.copy(bankId = null)) - ingestIncomingPayment(db, ingestCfg, incoming) + registerIncomingPayment(db, ingestCfg, incoming.copy(bankId = null)) + registerIncomingPayment(db, ingestCfg, incoming) } // Revenue API diff --git a/nexus/src/test/kotlin/helpers.kt b/nexus/src/test/kotlin/helpers.kt @@ -28,10 +28,12 @@ import tech.libeufin.common.* import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import tech.libeufin.nexus.* -import tech.libeufin.nexus.cli.ingestIncomingPayment -import tech.libeufin.nexus.cli.ingestOutgoingPayment +import tech.libeufin.nexus.cli.registerIncomingPayment +import tech.libeufin.nexus.cli.registerOutgoingPayment import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.db.InitiatedPayment +import tech.libeufin.nexus.ebics.randEbicsId +import tech.libeufin.nexus.iso20022.* import java.time.Instant import kotlin.io.path.Path @@ -81,15 +83,17 @@ fun getMockedClient( /** Generates a payment initiation, given its subject */ fun genInitPay( + endToEndId: String, subject: String = "init payment", - requestUid: String = "unique" + amount: String = "KUDOS:44", + creditorPayto: IbanPayto = ibanPayto("CH4189144589712575493", "Test") ) = InitiatedPayment( id = -1, - amount = TalerAmount(44, 0, "KUDOS"), - creditPaytoUri = "payto://iban/CH4189144589712575493?receiver-name=Test", - wireTransferSubject = subject, + amount = TalerAmount(amount), + creditor = creditorPayto, + subject = subject, initiationTime = Instant.now(), - requestUid = requestUid + endToEndId = endToEndId ) /** Generates an incoming payment, given its subject */ @@ -97,38 +101,28 @@ fun genInPay( subject: String, amount: String = "KUDOS:44", executionTime: Instant = Instant.now() -): IncomingPayment { - val bankId = run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } - return IncomingPayment( +) = IncomingPayment( amount = TalerAmount(amount), - debitPaytoUri = "payto://iban/not-used", - wireTransferSubject = subject, + debtorPayto = ibanPayto("DE84500105177118117964"), + subject = subject, executionTime = executionTime, - bankId = bankId + bankId = randEbicsId(), ) -} -/** Generates an outgoing payment, given its subject and messageId */ +/** Generates an outgoing payment, given its subject and end-to-end ID */ fun genOutPay( - subject: String, - messageId: String? = null, + subject: String, + endToEndId: String? = null, + msgId: String? = null, executionTime: Instant = Instant.now() -): OutgoingPayment { - val id = messageId ?: run { - val bytes = ByteArray(16).rand() - Base32Crockford.encode(bytes) - } - return OutgoingPayment( +) = OutgoingPayment( amount = TalerAmount(44, 0, "KUDOS"), - creditPaytoUri = "payto://iban/CH4189144589712575493?receiver-name=Test", - wireTransferSubject = subject, + creditorPayto = ibanPayto("CH4189144589712575493", "Test"), + subject = subject, executionTime = executionTime, - messageId = id + endToEndId = endToEndId ?: randEbicsId(), + msgId = msgId ) -} /** Perform a taler outgoing transaction */ suspend fun ApplicationTestBuilder.transfer() { @@ -165,16 +159,16 @@ suspend fun ApplicationTestBuilder.addKyc(amount: String) { }.assertOk() } -/** Ingest a talerable outgoing transaction */ +/** Register a talerable outgoing transaction */ suspend fun talerableOut(db: Database) { val wtid = ShortHashCode.rand() - ingestOutgoingPayment(db, genOutPay("$wtid http://exchange.example.com/")) + registerOutgoingPayment(db, genOutPay("$wtid http://exchange.example.com/")) } -/** Ingest a talerable reserve incoming transaction */ +/** Register a talerable reserve incoming transaction */ suspend fun talerableIn(db: Database, nullId: Boolean = false, amount: String = "CHF:44") { val reserve_pub = ShortHashCode.rand() - ingestIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), + registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), genInPay("test with $reserve_pub reserve pub", amount).run { if (nullId) { copy(bankId = null) @@ -185,10 +179,10 @@ suspend fun talerableIn(db: Database, nullId: Boolean = false, amount: String = ) } -/** Ingest a talerable KYC incoming transaction */ +/** Register a talerable KYC incoming transaction */ suspend fun talerableKycIn(db: Database, nullId: Boolean = false, amount: String = "CHF:44") { val account_pub = ShortHashCode.rand() - ingestIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), + registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), genInPay("test with KYC:$account_pub account pub", amount).run { if (nullId) { copy(bankId = null) @@ -199,14 +193,14 @@ suspend fun talerableKycIn(db: Database, nullId: Boolean = false, amount: String ) } -/** Ingest an incoming transaction */ -suspend fun ingestIn(db: Database) { - ingestIncomingPayment(db, NexusIngestConfig.default(AccountType.normal), genInPay("ignored")) +/** Register an incoming transaction */ +suspend fun registerIn(db: Database) { + registerIncomingPayment(db, NexusIngestConfig.default(AccountType.normal), genInPay("ignored")) } -/** Ingest an outgoing transaction */ -suspend fun ingestOut(db: Database) { - ingestOutgoingPayment(db, genOutPay("ignored")) +/** Register an outgoing transaction */ +suspend fun registerOut(db: Database) { + registerOutgoingPayment(db, genOutPay("ignored")) } /* ----- Auth ----- */ diff --git a/testbench/clean_test_logs.py b/testbench/clean_test_logs.py @@ -0,0 +1,75 @@ +#!/usr/bin/python3 +# Clean testbench logs directory to only keep unique and useful files + +import hashlib +from pathlib import Path +from string import whitespace + +DIR = Path("test") + + +def rmtree(p: Path): + """Recursively delete file or directory""" + if p.is_file(): + p.unlink() + else: + for child in p.iterdir(): + rmtree(child) + p.rmdir() + + +def remove(p: Path, reason: str): + """Announce and recursively remove file or directory""" + print(f"rm {reason} {p}") + rmtree(p) + + +content_hashes = set() + + +def rm_if_similar(p: Path, content: str): + """Delete file if another file has the same content""" + # Remove whitespace from file + normalized = content.translate(str.maketrans("", "", whitespace)) + # Hash their content + hash = hashlib.blake2b(normalized.encode(), usedforsecurity=False).hexdigest() + if hash in content_hashes: + remove(p, "similar") + else: + content_hashes.add(hash) + + +for platform in DIR.iterdir(): + if not platform.is_dir(): + continue + for date in platform.iterdir(): + if not date.is_dir(): + continue + for request in date.iterdir(): + payload_file_path = request.joinpath("payload.xml") + payload_dir_path = request.joinpath("payload") + + if payload_file_path.exists(): + content = payload_file_path.read_text() + if "HAC" in request.name and "ORDER_HAC_FINAL_NEG" not in content: + remove(request, "simple hac") + continue + elif "HAA" in request.name and "<Service>" not in content: + remove(request, "empty haa") + continue + rm_if_similar(payload_file_path, content) + elif payload_dir_path.exists(): + for file in payload_dir_path.iterdir(): + content = file.read_text() + rm_if_similar(file, content) + + if ( + request.name != "fetch" + and request.name != "submit" + and not payload_file_path.exists() + and not payload_dir_path.exists() + ): + remove(request, "empty request") + + if not any(date.iterdir()): + remove(request, "empty dir") diff --git a/testbench/sample/200519_camt054-Debit_P_CH2909000000250094239_1110092692_0_2019042401501580.xml b/testbench/sample/200519_camt054-Debit_P_CH2909000000250094239_1110092692_0_2019042401501580.xml @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04 file:///C:/Users/alihodzica/Desktop/camt.054/camt.054.001.04.xsd"> - <BkToCstmrDbtCdtNtfctn> - <GrpHdr> - <MsgId>20190424375204222704046</MsgId> - <CreDtTm>2014-04-25T01:49:54</CreDtTm> - <MsgPgntn> - <PgNb>1</PgNb> - <LastPgInd>true</LastPgInd> - </MsgPgntn> - <AddtlInf>SPS/1.6/PROD</AddtlInf> - </GrpHdr> - <Ntfctn> - <Id>20190424375204222704047</Id> - <CreDtTm>2019-04-25T01:49:54</CreDtTm> - <FrToDt> - <FrDtTm>2019-04-25T01:49:54</FrDtTm> - <ToDtTm>2019-04-25T01:49:54</ToDtTm> - </FrToDt> - <RptgSrc> - <Prtry>DBTN</Prtry> - </RptgSrc> - <Acct> - <Id> - <IBAN>CH2909000000250094239</IBAN> - </Id> - <Ownr> - <Nm>Robert Schneider SA Grands magasins Biel/Bienne</Nm> - </Ownr> - </Acct> - <Ntry> - <Amt Ccy="CHF">913.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <RvslInd>false</RvslInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2019-04-25</Dt> - </BookgDt> - <ValDt> - <Dt>2019-04-25</Dt> - </ValDt> - <AcctSvcrRef>074820002ZU1EQ0K</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>ICDT</Cd> - <SubFmlyCd>AUTT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <TxDtls> - <Refs> - <MsgId>20190424-000369773</MsgId> - <AcctSvcrRef>25-1120172999-2</AcctSvcrRef> - <PmtInfId>30003101</PmtInfId> - <EndToEndId>20190424001255000100006</EndToEndId> - </Refs> - <Amt Ccy="CHF">913.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101</AddtlNtryInf> - </Ntry> - </Ntfctn> - </BkToCstmrDbtCdtNtfctn> -</Document> diff --git a/testbench/sample/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2019.xml b/testbench/sample/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2019.xml @@ -1,131 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04 file:///C:/Users/alihodzica/Desktop/camt.054/camt.054.001.04.xsd"> - <BkToCstmrDbtCdtNtfctn> - <GrpHdr> - <MsgId>20190424375204228750928</MsgId> - <CreDtTm>2019-04-25T00:20:05</CreDtTm> - <MsgPgntn> - <PgNb>1</PgNb> - <LastPgInd>true</LastPgInd> - </MsgPgntn> - <AddtlInf>SPS/2.0/PROD</AddtlInf> - </GrpHdr> - <Ntfctn> - <Id>20190424375204228750931</Id> - <CreDtTm>2019-04-25T00:20:05</CreDtTm> - <FrToDt> - <FrDtTm>2019-04-24T00:00:00</FrDtTm> - <ToDtTm>2019-04-24T23:59:59</ToDtTm> - </FrToDt> - <Acct> - <Id> - <IBAN>CH2909000000250094239</IBAN> - </Id> - <Ccy>CHF</Ccy> - <Ownr> - <Nm>Robert Schneider SA</Nm> - </Ownr> - </Acct> - <Ntry> - <NtryRef>020010001</NtryRef> - <Amt Ccy="CHF">147.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <RvslInd>false</RvslInd> - <Sts> - <Cd>BOOK</Cd> - </Sts> - <BookgDt> - <Dt>2019-04-24</Dt> - </BookgDt> - <ValDt> - <Dt>2019-04-25</Dt> - </ValDt> - <AcctSvcrRef>100820002V496ZRA</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>CNTR</Cd> - <SubFmlyCd>CWDL</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <Chrgs> - <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> - <Rcrd> - <Amt Ccy="CHF">4.40</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <ChrgInclInd>false</ChrgInclInd> - <Tp> - <Prtry> - <Id>6</Id> - </Prtry> - </Tp> - </Rcrd> - </Chrgs> - <NtryDtls> - <Btch> - <NbOfTxs>1</NbOfTxs> - </Btch> - <TxDtls> - <Refs> - <AcctSvcrRef>180410CH02UZ2PC1</AcctSvcrRef> - <Prtry> - <Tp>06</Tp> - <Ref>20190423848301000100105</Ref> - </Prtry> - </Refs> - <Amt Ccy="CHF">147.00</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>CNTR</Cd> - <SubFmlyCd>CWDL</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <Chrgs> - <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> - <Rcrd> - <Amt Ccy="CHF">4.40</Amt> - <CdtDbtInd>DBIT</CdtDbtInd> - <ChrgInclInd>false</ChrgInclInd> - <Tp> - <Prtry> - <Id>6</Id> - </Prtry> - </Tp> - </Rcrd> - </Chrgs> - <RltdPties> - <Cdtr> - <Pty> - <Nm>Maria Bernasconi</Nm> - </Pty> - </Cdtr> - <CdtrAcct> - <Id> - <IBAN>CH5109000000250092291</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RmtInf> - <Strd> - <CdtrRefInf> - <Ref>100041698214115449371805278</Ref> - </CdtrRefInf> - <AddtlRmtInf>?REJECT?0</AddtlRmtInf> - </Strd> - </RmtInf> - <RltdDts> - <AccptncDtTm>2019-04-23T20:00:00</AccptncDtTm> - </RltdDts> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>SAMMELLASTSCHRIFT ASR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 02-1000-1 PAKET ID: 180410CH00000AL0</AddtlNtryInf> - </Ntry> - </Ntfctn> - </BkToCstmrDbtCdtNtfctn> -</Document> diff --git a/testbench/sample/200519_camt054_P_CH2909000000250094239_1111091335_0_2020061900081727_v2009.xml b/testbench/sample/200519_camt054_P_CH2909000000250094239_1111091335_0_2020061900081727_v2009.xml @@ -1,207 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04 camt.054.001.04.xsd"> - <BkToCstmrDbtCdtNtfctn> - <GrpHdr> - <MsgId>20200618375204295372463</MsgId> - <CreDtTm>2020-06-18T23:41:07</CreDtTm> - <MsgPgntn> - <PgNb>1</PgNb> - <LastPgInd>true</LastPgInd> - </MsgPgntn> - <AddtlInf>SPS/1.7/PROD</AddtlInf> - </GrpHdr> - <Ntfctn> - <Id>20200618375204295372465</Id> - <CreDtTm>2020-06-18T23:41:07</CreDtTm> - <FrToDt> - <FrDtTm>2020-06-18T00:00:00</FrDtTm> - <ToDtTm>2020-06-18T23:59:59</ToDtTm> - </FrToDt> - <RptgSrc> - <Prtry>OTHR</Prtry> - </RptgSrc> - <Acct> - <Id> - <IBAN>CH2909000000250094239</IBAN> - </Id> - <Ownr> - <Nm>Robert Schneider SA Grands magasins Biel/Bienne</Nm> - </Ownr> - </Acct> - <Ntry> - <NtryRef>CH7730000001250094239</NtryRef> - <Amt Ccy="CHF">1692.22</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <RvslInd>false</RvslInd> - <Sts>BOOK</Sts> - <BookgDt> - <Dt>2020-06-18</Dt> - </BookgDt> - <ValDt> - <Dt>2020-06-18</Dt> - </ValDt> - <AcctSvcrRef>1000000000000000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>VCOM</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <Btch> - <NbOfTxs>2</NbOfTxs> - </Btch> - <TxDtls> - <Refs> - <AcctSvcrRef>2000000000000000</AcctSvcrRef> - <InstrId>1006265-25bbb3b1a</InstrId> - <EndToEndId>1006265-aic5dL-75dzf3jk9-cf2d5e9</EndToEndId> - <Prtry> - <Tp>00</Tp> - <Ref>00000000000000000000020</Ref> - </Prtry> - </Refs> - <Amt Ccy="CHF">778.29</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>AUTT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Bernasconi Maria</Nm> - <PstlAdr> - <StrtNm>Place de la Gare</StrtNm> - <BldgNb>12</BldgNb> - <PstCd>2502</PstCd> - <TwnNm>Biel/Bienne</TwnNm> - <Ctry>CH</Ctry> - </PstlAdr> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>CH5109000000250092291</IBAN> - </Id> - </DbtrAcct> - <CdtrAcct> - <Id> - <IBAN>CH7730000001250094239</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BICFI>POFICHBEXXX</BICFI> - <Nm>POSTFINANCE AG</Nm> - <PstlAdr> - <AdrLine>MINGERSTRASSE 20</AdrLine> - <AdrLine>3030 BERNE</AdrLine> - </PstlAdr> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Strd> - <CdtrRefInf> - <Tp> - <CdOrPrtry> - <Prtry>QRR</Prtry> - </CdOrPrtry> - </Tp> - <Ref>539115429773825311971477453</Ref> - </CdtrRefInf> - <AddtlRmtInf>?REJECT?0</AddtlRmtInf> - <AddtlRmtInf>?ERROR?000</AddtlRmtInf> - </Strd> - </RmtInf> - <RltdDts> - <AccptncDtTm>2020-06-18T20:00:00</AccptncDtTm> - </RltdDts> - </TxDtls> - <TxDtls> - <Refs> - <AcctSvcrRef>3000000000000000</AcctSvcrRef> - <InstrId>1005970-70a75515</InstrId> - <Prtry> - <Tp>00</Tp> - <Ref>00000000000000000000030</Ref> - </Prtry> - </Refs> - <Amt Ccy="CHF">913.93</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>AUTT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Nm>Bernasconi Maria</Nm> - <PstlAdr> - <StrtNm>Place de la Gare</StrtNm> - <BldgNb>12</BldgNb> - <PstCd>2502</PstCd> - <TwnNm>Biel/Bienne</TwnNm> - <Ctry>CH</Ctry> - </PstlAdr> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>CH5109000000250092291</IBAN> - </Id> - </DbtrAcct> - <CdtrAcct> - <Id> - <IBAN>CH7730000001250094239</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BICFI>POFICHBEXXX</BICFI> - <Nm>POSTFINANCE AG</Nm> - <PstlAdr> - <AdrLine>MINGERSTRASSE 20</AdrLine> - <AdrLine>3030 BERNE</AdrLine> - </PstlAdr> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Strd> - <CdtrRefInf> - <Tp> - <CdOrPrtry> - <Prtry>QRR</Prtry> - </CdOrPrtry> - </Tp> - <Ref>662437765447746478179744715</Ref> - </CdtrRefInf> - <AddtlRmtInf>?REJECT?0</AddtlRmtInf> - <AddtlRmtInf>?ERROR?000</AddtlRmtInf> - </Strd> - </RmtInf> - <RltdDts> - <AccptncDtTm>2020-06-18T20:00:00</AccptncDtTm> - </RltdDts> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>SAMMELGUTSCHRIFT FÜR KONTO: CH7730000001250094239 VERARBEITUNG VOM 18.06.2020 PAKET ID: 200618CH000009TB</AddtlNtryInf> - </Ntry> - </Ntfctn> - </BkToCstmrDbtCdtNtfctn> -</Document> diff --git a/testbench/sample/200519_camt054_P_CH2909000000250094239_1111091335_0_2020061900081727_v2019.xml b/testbench/sample/200519_camt054_P_CH2909000000250094239_1111091335_0_2020061900081727_v2019.xml @@ -1,212 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08 file:///C:/Users/burkhalterl/Documents/Musterfiles%20ISOV19/Schemen/camt.054.001.08.xsd"> - <BkToCstmrDbtCdtNtfctn> - <GrpHdr> - <MsgId>20200618375204295372463</MsgId> - <CreDtTm>2020-06-18T23:41:07</CreDtTm> - <MsgPgntn> - <PgNb>1</PgNb> - <LastPgInd>true</LastPgInd> - </MsgPgntn> - <AddtlInf>SPS/2.0/PROD</AddtlInf> - </GrpHdr> - <Ntfctn> - <Id>20200618375204295372465</Id> - <CreDtTm>2020-06-18T23:41:07</CreDtTm> - <FrToDt> - <FrDtTm>2020-06-18T00:00:00</FrDtTm> - <ToDtTm>2020-06-18T23:59:59</ToDtTm> - </FrToDt> - <Acct> - <Id> - <IBAN>CH2909000000250094239</IBAN> - </Id> - <Ccy>CHF</Ccy> - <Ownr> - <Nm>Robert Schneider SA Grands magasins Biel/Bienne</Nm> - </Ownr> - </Acct> - <Ntry> - <NtryRef>CH7730000001250094239</NtryRef> - <Amt Ccy="CHF">1692.22</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <RvslInd>false</RvslInd> - <Sts> - <Cd>BOOK</Cd> - </Sts> - <BookgDt> - <Dt>2020-06-18</Dt> - </BookgDt> - <ValDt> - <Dt>2020-06-18</Dt> - </ValDt> - <AcctSvcrRef>1000000000000000</AcctSvcrRef> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>VCOM</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <NtryDtls> - <Btch> - <NbOfTxs>2</NbOfTxs> - </Btch> - <TxDtls> - <Refs> - <AcctSvcrRef>2000000000000000</AcctSvcrRef> - <InstrId>1006265-25bbb3b1a</InstrId> - <EndToEndId>1006265-aic5dL-75dzf3jk9-cf2d5e9</EndToEndId> - <UETR>b009c997-97b3-4a9c-803c-d645a7276bf0</UETR> - <Prtry> - <Tp>00</Tp> - <Ref>00000000000000000000020</Ref> - </Prtry> - </Refs> - <Amt Ccy="CHF">778.29</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>AUTT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Pty> - <Nm>Bernasconi Maria</Nm> - <PstlAdr> - <StrtNm>Place de la Gare</StrtNm> - <BldgNb>12</BldgNb> - <PstCd>2502</PstCd> - <TwnNm>Biel/Bienne</TwnNm> - <Ctry>CH</Ctry> - </PstlAdr> - </Pty> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>CH5109000000250092291</IBAN> - </Id> - </DbtrAcct> - <CdtrAcct> - <Id> - <IBAN>CH7730000001250094239</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BICFI>POFICHBEXXX</BICFI> - <Nm>POSTFINANCE AG</Nm> - <PstlAdr> - <AdrLine>MINGERSTRASSE 20</AdrLine> - <AdrLine>3030 BERNE</AdrLine> - </PstlAdr> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Strd> - <CdtrRefInf> - <Tp> - <CdOrPrtry> - <Prtry>QRR</Prtry> - </CdOrPrtry> - </Tp> - <Ref>539115429773825311971477453</Ref> - </CdtrRefInf> - <AddtlRmtInf>?REJECT?0</AddtlRmtInf> - <AddtlRmtInf>?ERROR?000</AddtlRmtInf> - </Strd> - </RmtInf> - <RltdDts> - <AccptncDtTm>2020-06-18T20:00:00</AccptncDtTm> - </RltdDts> - </TxDtls> - <TxDtls> - <Refs> - <AcctSvcrRef>3000000000000000</AcctSvcrRef> - <InstrId>1005970-70a75515</InstrId> - <Prtry> - <Tp>00</Tp> - <Ref>00000000000000000000030</Ref> - </Prtry> - </Refs> - <Amt Ccy="CHF">913.93</Amt> - <CdtDbtInd>CRDT</CdtDbtInd> - <BkTxCd> - <Domn> - <Cd>PMNT</Cd> - <Fmly> - <Cd>RCDT</Cd> - <SubFmlyCd>AUTT</SubFmlyCd> - </Fmly> - </Domn> - </BkTxCd> - <RltdPties> - <Dbtr> - <Pty> - <Nm>Bernasconi Maria</Nm> - <PstlAdr> - <StrtNm>Place de la Gare</StrtNm> - <BldgNb>12</BldgNb> - <PstCd>2502</PstCd> - <TwnNm>Biel/Bienne</TwnNm> - <Ctry>CH</Ctry> - </PstlAdr> - </Pty> - </Dbtr> - <DbtrAcct> - <Id> - <IBAN>CH5109000000250092291</IBAN> - </Id> - </DbtrAcct> - <CdtrAcct> - <Id> - <IBAN>CH7730000001250094239</IBAN> - </Id> - </CdtrAcct> - </RltdPties> - <RltdAgts> - <DbtrAgt> - <FinInstnId> - <BICFI>POFICHBEXXX</BICFI> - <Nm>POSTFINANCE AG</Nm> - <PstlAdr> - <AdrLine>MINGERSTRASSE 20</AdrLine> - <AdrLine>3030 BERNE</AdrLine> - </PstlAdr> - </FinInstnId> - </DbtrAgt> - </RltdAgts> - <RmtInf> - <Strd> - <CdtrRefInf> - <Tp> - <CdOrPrtry> - <Prtry>QRR</Prtry> - </CdOrPrtry> - </Tp> - <Ref>662437765447746478179744715</Ref> - </CdtrRefInf> - <AddtlRmtInf>?REJECT?0</AddtlRmtInf> - <AddtlRmtInf>?ERROR?000</AddtlRmtInf> - </Strd> - </RmtInf> - <RltdDts> - <AccptncDtTm>2020-06-18T20:00:00</AccptncDtTm> - </RltdDts> - </TxDtls> - </NtryDtls> - <AddtlNtryInf>SAMMELGUTSCHRIFT FÜR KONTO: CH7730000001250094239 VERARBEITUNG VOM 18.06.2020 PAKET ID: 200618CH000009TB</AddtlNtryInf> - </Ntry> - </Ntfctn> - </BkToCstmrDbtCdtNtfctn> -</Document> diff --git a/testbench/sample/cs/QRIBAN_camt.054_SIC_04_088583185407_NN_0885831854071000_20221222_180251_006.xml b/testbench/sample/cs/QRIBAN_camt.054_SIC_04_088583185407_NN_0885831854071000_20221222_180251_006.xml @@ -0,0 +1,427 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>CAMT054_20221222_180251119_4Z2WCTQ4</MsgId> + <CreDtTm>2022-12-22T17:02:51.119Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.7/PROD</AddtlInf> + </GrpHdr> + <Ntfctn> + <Id>4BA01709118000076</Id> + <CreDtTm>2022-12-22T17:02:51.119Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-12-22T00:00:00.000+01:00</FrDtTm> + <ToDtTm>2022-12-22T23:59:59.999+01:00</ToDtTm> + </FrToDt> + <RptgSrc> + <Prtry>C53F</Prtry> + </RptgSrc> + <Acct> + <Id> + <IBAN>CH5104835831854071000</IBAN> + </Id> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Ntry> + <NtryRef>CH4531000831854071000</NtryRef> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2010-12-22</Dt> + </ValDt> + <AcctSvcrRef>4BA01709118000076/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">997.25</Amt> + </TxAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">2.85</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">2.85</Amt> + <ChrgInclInd>false</ChrgInclInd> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>4BA01709118000076</MsgId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">997.25</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65113</MsgId> + <AcctSvcrRef>80XI-190418-CS-80256</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65113</PmtInfId> + <EndToEndId>EndToEndId-0000000010</EndToEndId> + </Refs> + <Amt Ccy="CHF">477.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">477.25</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>Example SA</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </Dbtr> + <UltmtDbtr> + <Nm>Example SA</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678028</Ref> + </CdtrRefInf> + <AddtlRmtInf>Déduction faite de 3% d'escompte</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65114</MsgId> + <AcctSvcrRef>80XI-190418-CS-80257</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65114</PmtInfId> + <EndToEndId>EndToEndId-0000000011</EndToEndId> + </Refs> + <Amt Ccy="CHF">140</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">140</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>Hans Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Dbtr> + <UltmtDbtr> + <Nm>Bäckerei-Konditorei Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678033</Ref> + </CdtrRefInf> + <AddtlRmtInf>Auftrag vom 15.02.2022</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65115</MsgId> + <AcctSvcrRef>80XI-190418-CS-80258</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65115</PmtInfId> + <EndToEndId>EndToEndId-0000000012</EndToEndId> + </Refs> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">120</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">2.45</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">2.35</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>2</Id> + </Prtry> + </Tp> + </Rcrd> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>SCHALTEREINZAHLUNG</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + </PstlAdr> + </Dbtr> + <UltmtDbtr> + <Nm>PETER MEIER</Nm> + <PstlAdr> + <StrtNm>SEMPACHERSTRASSE</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>6789</PstCd> + <TwnNm>MITTELDORF</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678049</Ref> + </CdtrRefInf> + <AddtlRmtInf>000000/00000/000000/17.02.2022</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65116</MsgId> + <AcctSvcrRef>80XI-190418-CS-80259</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65116</PmtInfId> + <EndToEndId>EndToEndId-0000000013</EndToEndId> + </Refs> + <Amt Ccy="CHF">110</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">110</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>RUTH MEIER</Nm> + <PstlAdr> + <AdrLine>OBERDORFSTRASSE 1 CH 5678 UNTERDORF</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678057</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65117</MsgId> + <AcctSvcrRef>80XI-190418-CS-80260</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65117</PmtInfId> + <EndToEndId>EndToEndId-0000000014</EndToEndId> + </Refs> + <Amt Ccy="CHF">150</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">150</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>Anna Meier</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Nachbardorfstrasse 1</AdrLine> + <AdrLine>9999 Obertal</AdrLine> + </PstlAdr> + </Dbtr> + <UltmtDbtr> + <Nm>Anna Meier</Nm> + <PstlAdr> + <StrtNm>Nachbardorfstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>9999</PstCd> + <TwnNm>Obertal</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678065</Ref> + </CdtrRefInf> + <AddtlRmtInf>Order 1234567</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/cs/QRIBAN_camt.054_SPS_08_088583185407_NN_0885831854071000_20221222_180251_006.xml b/testbench/sample/cs/QRIBAN_camt.054_SPS_08_088583185407_NN_0885831854071000_20221222_180251_006.xml @@ -0,0 +1,456 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- camt.054 for QR-bills with QR-IBAN, structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>CAMT054_20221222_180251119_4Z2WCTQ4</MsgId> + <CreDtTm>2022-12-22T17:02:51.119Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/2.0/PROD</AddtlInf> + </GrpHdr> + <Ntfctn> + <Id>4BA01709118000076</Id> + <CreDtTm>2022-03-22T17:02:51.119Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-12-22T00:00:00.000+01:00</FrDtTm> + <ToDtTm>2022-12-22T23:59:59.999+01:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <IBAN>CH5104835831854071000</IBAN> + </Id> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Ntry> + <NtryRef>CH4531000831854071000</NtryRef> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2010-12-22</Dt> + </ValDt> + <AcctSvcrRef>4BA01709118000076/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">997.25</Amt> + </TxAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">2.85</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">2.85</Amt> + <ChrgInclInd>false</ChrgInclInd> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>4BA01709118000076</MsgId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">997.25</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65113</MsgId> + <AcctSvcrRef>80XI-190418-CS-80256</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65113</PmtInfId> + <EndToEndId>EndToEndId-0000000010</EndToEndId> + <UETR>eb6305c9-1f7f-49de-aed0-16487c27b42d</UETR> + </Refs> + <Amt Ccy="CHF">477.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">477.25</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Example SA</Nm> + </Pty> + </InitgPty> + <Dbtr> + <Pty> + <Nm>Example SA</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + <UltmtDbtr> + <Pty> + <Nm>Example SA</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </Pty> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678028</Ref> + </CdtrRefInf> + <AddtlRmtInf>Déduction faite de 3% d'escompte</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65114</MsgId> + <AcctSvcrRef>80XI-190418-CS-80257</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65114</PmtInfId> + <EndToEndId>EndToEndId-0000000011</EndToEndId> + <UETR>eb6305c9-1f7f-49de-aed0-16487c27b42b</UETR> + </Refs> + <Amt Ccy="CHF">140</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">140</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </InitgPty> + <Dbtr> + <Pty> + <Nm>Hans Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Dbtr> + <UltmtDbtr> + <Pty> + <Nm>Bäckerei-Konditorei Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678033</Ref> + </CdtrRefInf> + <AddtlRmtInf>Auftrag vom 15.02.2022</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65115</MsgId> + <AcctSvcrRef>80XI-190418-CS-80258</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65115</PmtInfId> + <EndToEndId>EndToEndId-0000000012</EndToEndId> + </Refs> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">120</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">2.45</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">2.35</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>2</Id> + </Prtry> + </Tp> + </Rcrd> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Pty> + <Nm>SCHALTEREINZAHLUNG</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Dbtr> + <UltmtDbtr> + <Pty> + <Nm>PETER MEIER</Nm> + <PstlAdr> + <StrtNm>SEMPACHERSTRASSE</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>6789</PstCd> + <TwnNm>MITTELDORF</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678049</Ref> + </CdtrRefInf> + <AddtlRmtInf>000000/00000/000000/17.12.2022</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65116</MsgId> + <AcctSvcrRef>80XI-190418-CS-80259</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65116</PmtInfId> + <EndToEndId>EndToEndId-0000000013</EndToEndId> + </Refs> + <Amt Ccy="CHF">110</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">110</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Pty> + <Nm>RUTH MEIER</Nm> + <PstlAdr> + <AdrLine>OBERDORFSTRASSE 1 CH 5678 UNTERDORF</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678057</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>13RF-190418-MS-65117</MsgId> + <AcctSvcrRef>80XI-190418-CS-80260</AcctSvcrRef> + <PmtInfId>13RF-190418-MS-65117</PmtInfId> + <EndToEndId>EndToEndId-0000000014</EndToEndId> + </Refs> + <Amt Ccy="CHF">150</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">150</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Anna Meier</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Nachbardorfstrasse 1</AdrLine> + <AdrLine>9999 Obertal</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + <UltmtDbtr> + <Pty> + <Nm>Anna Meier</Nm> + <PstlAdr> + <StrtNm>Nachbardorfstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>9999</PstCd> + <TwnNm>Obertal</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678065</Ref> + </CdtrRefInf> + <AddtlRmtInf>Order 1234567</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/cs/camt.052_SIC_04_050483017844_ND_0504830178442001_20171127_230054_001.xml b/testbench/sample/cs/camt.052_SIC_04_050483017844_ND_0504830178442001_20171127_230054_001.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.04"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>CAMT052_20171127_230054037_5R83DWV3</MsgId> + <CreDtTm>2017-11-27T23:00:54.038Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.7/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>4c41ae16ae0a41bda7575de162e53b2a</Id> + <ElctrncSeqNb>4</ElctrncSeqNb> + <CreDtTm>2017-11-27T23:00:54.149Z</CreDtTm> + <Acct> + <Id> + <Othr> + <Id>0504830178442001</Id> + </Othr> + </Id> + <Ccy>EUR</Ccy> + <Ownr> + <Nm>Your Company Name</Nm> + <PstlAdr> + <AdrLine>Adress Line</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">582975.5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">808704.88</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>50</NbOfNtries> + <Sum>333005.56</Sum> + <TtlNetNtry> + <Amt>225729.38</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>22</NbOfNtries> + <Sum>53638.09</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>28</NbOfNtries> + <Sum>279367.47</Sum> + </TtlDbtNtries> + </TxsSummry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/cs/camt.052_SIC_04_050483017844_WD_0504830178442001_20171127_230054_002.xml b/testbench/sample/cs/camt.052_SIC_04_050483017844_WD_0504830178442001_20171127_230054_002.xml @@ -0,0 +1,6702 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.04"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>CAMT052_20171127_230054396_2XFDFW86</MsgId> + <CreDtTm>2017-11-27T23:00:54.396Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.7/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>3edc45b55b044b0aa909e458b9c551d2</Id> + <ElctrncSeqNb>4</ElctrncSeqNb> + <CreDtTm>2017-11-27T23:00:54.402Z</CreDtTm> + <Acct> + <Id> + <Othr> + <Id>0504830178442001</Id> + </Othr> + </Id> + <Ccy>EUR</Ccy> + <Ownr> + <Nm>Your Company Name</Nm> + <PstlAdr> + <AdrLine>Adress Line</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">582975.5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">808704.88</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>50</NbOfNtries> + <Sum>333005.56</Sum> + <TtlNetNtry> + <Amt>225729.38</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>22</NbOfNtries> + <Sum>53638.09</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>28</NbOfNtries> + <Sum>279367.47</Sum> + </TtlDbtNtries> + </TxsSummry> + <Ntry> + <Amt Ccy="EUR">903.61</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37494/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">1042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">1042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">903.61</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37494</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">904.47</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37499/2</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">1043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">1043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">904.47</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86718</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37499</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1770.79</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37495/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">2042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">2042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1770.79</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86718</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37495</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1771.66</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37500/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">2043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">2043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1771.66</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37500</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2637.98</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37496/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">3042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">3042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2637.98</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37496</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2638.85</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37501/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">3043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">3043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2638.85</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37501</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3505.17</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37497/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">4042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">4042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3505.17</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37497</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3506.03</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37502/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">4043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">4043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3506.03</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37502</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4372.35</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37498/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">4372.35</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37498</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4373.22</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37503/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">4373.22</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37503</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-B-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13155.32</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88144/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15200</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15200</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13155.32</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548158</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15200</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03640</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03651</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03662</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03673</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03684</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13159.64</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88145/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15205</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15205</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13159.64</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548109</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15205</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03695</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03606</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03717</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03728</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03739</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP04-A-POS2</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13241.86</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88152/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15300</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15300</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13241.86</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548105</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP06-POS2</MsgId> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15300</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03740</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03751</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03762</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03773</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03784</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 4</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13246.19</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88153/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15305</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15305</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13246.19</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548122</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP06-POS2</MsgId> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15305</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03795</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03806</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03817</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03828</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03839</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13273.3</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88136/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15000</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13273.3</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488667</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP01-POS3</MsgId> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15000</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03840</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-01</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>111111111111111111111111110</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03851</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-02</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>222222222222222222222222222</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03862</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-03</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>333333333333333333333333334</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03873</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-04</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>444444444444444444444444444</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03884</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-05</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>555555555555555555555555559</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13332.74</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88155/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15405</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15405</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13332.74</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548134</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP08-POS2</MsgId> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15405</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03895</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-01</EndToEndId> + <ChqNb>36501096</ChqNb> + </Refs> + <Amt Ccy="USD">1081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03906</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-02</EndToEndId> + <ChqNb>36501097</ChqNb> + </Refs> + <Amt Ccy="USD">2081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>2</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03917</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-03</EndToEndId> + <ChqNb>36501098</ChqNb> + </Refs> + <Amt Ccy="USD">3081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>3</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03928</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-04</EndToEndId> + <ChqNb>36501099</ChqNb> + </Refs> + <Amt Ccy="USD">4081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03939</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-05</EndToEndId> + <ChqNb>36501100</ChqNb> + </Refs> + <Amt Ccy="USD">5081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>5</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13361.79</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88138/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15100</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15100</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13361.79</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488675</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP02-POS2</MsgId> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15100</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03940</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03951</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03962</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03973</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03984</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13406.04</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88140/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15150</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15150</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13406.04</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488713</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15150</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03995</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-01</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04006</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-02</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04017</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-03</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04028</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-04</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04039</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-05</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13414.89</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88142/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15160</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15160</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13414.89</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.8848872</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP03-B-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15160</TtlAmt> + </Btch> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13419.31</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88143/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15165</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15165</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13419.31</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488691</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP03-B-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15165</TtlAmt> + </Btch> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13627.26</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88154/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15400</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15400</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13627.26</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488701</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP08-POS2</MsgId> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15400</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04040</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-04</EndToEndId> + <ChqNb>36501094</ChqNb> + </Refs> + <Amt Ccy="CHF">4080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04051</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-03</EndToEndId> + <ChqNb>36501093</ChqNb> + </Refs> + <Amt Ccy="CHF">3080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>3</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04062</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-05</EndToEndId> + <ChqNb>36501095</ChqNb> + </Refs> + <Amt Ccy="CHF">5080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>5</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04073</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-01</EndToEndId> + <ChqNb>36501091</ChqNb> + </Refs> + <Amt Ccy="CHF">1080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04084</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-02</EndToEndId> + <ChqNb>36501092</ChqNb> + </Refs> + <Amt Ccy="CHF">2080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>2</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> </Pty> + </Prtry> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15055</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88137/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15055</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15055</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP01-POS3</MsgId> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15055</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04084</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-04</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>444444444444444444444444444</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04095</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-05</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>555555555555555555555555559</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04106</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-01</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>111111111111111111111111110</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04117</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-02</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>222222222222222222222222222</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04128</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-03</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP01-POS3</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>333333333333333333333333334</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15105</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88139/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15105</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15105</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP02-POS2</MsgId> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15105</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04139</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04140</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04151</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04162</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04173</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15155</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88141/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15155</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15155</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15155</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04184</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-04</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04195</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-05</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04206</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-02</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04217</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-03</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04228</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-01</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15250</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88148/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15250</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15250</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15250</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04239</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04240</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04251</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04262</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04273</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15255</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88149/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15255</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15255</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15255</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04284</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04295</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04306</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04317</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04328</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15260</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88150/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15260</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15260</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15260</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04339</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04340</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04351</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04362</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04373</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15265</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88151/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15265</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15265</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15265</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04384</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0495</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0506</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0517</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0528</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Max Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">881.87</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36700/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">913.28889</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36700</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">1030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">883.59</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36739/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">915.06227</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36739</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">1032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">884.44</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36746/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">915.94896</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36746</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">1033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">900</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36835/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">1000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">900</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36835</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR11171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">900</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1738.06</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36701/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1799.97714</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36701</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">2030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1739.77</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36747/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1801.75052</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36747</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">2032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1740.63</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36748/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1802.63721</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36748</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">2033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1800</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36836/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">2000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">1800</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36836</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR12171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">1800</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2594.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36702/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2686.66539</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36702</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">3030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2595.96</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36749/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2688.43876</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36749</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">3032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2596.82</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36750/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2689.32545</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36750</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">3033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2654.18</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36830/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3100</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2654.18</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36830</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF117171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3100</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2700</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36839/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">3000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">2700</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49200</MsgId> + <AcctSvcrRef>80VA-171127-CS-36839</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49200</PmtInfId> + <EndToEndId>E2EPBP13-INEUR13171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">2700</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2739.8</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36831/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3200</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2739.8</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36831</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF127171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3200</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2825.42</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36832/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3300</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2825.42</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36832</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF137171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3300</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2911.04</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36833/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3400</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2911.04</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36833</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF147171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3400</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2996.66</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36834/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3500</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2996.66</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36834</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF157171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3450.44</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36703/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3573.35363</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36703</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">4030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3452.15</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36751/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3575.12701</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36751</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">4032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3453.01</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36752/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3576.0137</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36752</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">4033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3600</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36837/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">4000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">3600</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36837</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR14171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">3600</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2017-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2017-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36838/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">5000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">4500</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2017-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36838</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR15171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">4500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13273.3</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>PDNG</Sts> + <ValDt> + <Dt>2017-11-15</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-80769</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>1520</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>1520</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">220000000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>PDNG</Sts> + <ValDt> + <Dt>2017-11-22</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-90770</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8017</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8017</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">10000000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>PDNG</Sts> + <ValDt> + <Dt>2017-11-22</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-90781</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8017</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8017</AddtlNtryInf> + </Ntry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/cs/camt.052_SPS_08_050483017844_ND_0504830178442001_20171127_230054_001.xml b/testbench/sample/cs/camt.052_SPS_08_050483017844_ND_0504830178442001_20171127_230054_001.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>CAMT052_20171127_230054037_5R83DWV3</MsgId> + <CreDtTm>2017-11-27T23:00:54.038Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.7/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>4c41ae16ae0a41bda7575de162e53b2a</Id> + <ElctrncSeqNb>4</ElctrncSeqNb> + <CreDtTm>2017-11-27T23:00:54.149Z</CreDtTm> + <Acct> + <Id> + <Othr> + <Id>0504830178442001</Id> + </Othr> + </Id> + <Ccy>EUR</Ccy> + <Ownr> + <Nm>Your Company Name</Nm> + <PstlAdr> + <AdrLine>Adress Line</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">582975.5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">808704.88</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2017-11-27</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>50</NbOfNtries> + <Sum>333005.56</Sum> + <TtlNetNtry> + <Amt>225729.38</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>22</NbOfNtries> + <Sum>53638.09</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>28</NbOfNtries> + <Sum>279367.47</Sum> + </TtlDbtNtries> + </TxsSummry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/cs/camt.052_SPS_08_050483017844_WD_0504830178442001_20221127_230054_002.xml b/testbench/sample/cs/camt.052_SPS_08_050483017844_WD_0504830178442001_20221127_230054_002.xml @@ -0,0 +1,7232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>CAMT052_20221127_230054396_2XFDFW86</MsgId> + <CreDtTm>2022-11-27T23:00:54.396+01:00</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/2.0/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>3edc45b55b044b0aa909e458b9c551d2</Id> + <ElctrncSeqNb>4</ElctrncSeqNb> + <CreDtTm>2022-11-27T23:00:54.402+01:00</CreDtTm> + <Acct> + <Id> + <Othr> + <Id>0504-8301784-42-001</Id> + </Othr> + </Id> + <Ccy>EUR</Ccy> + <Ownr> + <Nm>Your Company Name</Nm> + <PstlAdr> + <AdrLine>Adress Line</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">582975.5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2022-11-27</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="EUR">808704.88</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Dt> + <Dt>2022-11-27</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>50</NbOfNtries> + <Sum>333005.56</Sum> + <TtlNetNtry> + <Amt>225729.38</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>22</NbOfNtries> + <Sum>53638.09</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>28</NbOfNtries> + <Sum>279367.47</Sum> + </TtlDbtNtries> + </TxsSummry> + <Ntry> + <Amt Ccy="EUR">903.61</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37494/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">1042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">1042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">903.61</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37494</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">904.47</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37499/2</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">1043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">1043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">904.47</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86718</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37499</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1770.79</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37495/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">2042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">2042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1770.79</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86718</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37495</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1771.66</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37500/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">2043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">2043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1771.66</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37500</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2637.98</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37496/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">3042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">3042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2637.98</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37496</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2638.85</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37501/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">3043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">3043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2638.85</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37501</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3505.17</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37497/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">4042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">4042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3505.17</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37497</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3506.03</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37502/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">4043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">4043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3506.03</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37502</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4372.35</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37498/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5042</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5042</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">4372.35</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37498</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5042</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4373.22</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNVA-171127-CS-37503/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5043</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5043</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">4373.22</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86719</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-B-POS2</MsgId> + <AcctSvcrRef>DNVA-171127-CS-37503</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-B-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP04-B-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5043</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-B-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13155.32</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88144/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15200</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15200</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13155.32</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548158</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15200</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03640</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03651</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03662</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03673</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03684</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3040</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13159.64</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88145/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15205</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15205</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13159.64</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548109</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15205</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03695</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03606</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03717</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03728</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP04-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03739</AcctSvcrRef> + <PmtInfId>PmtInfId-BP04-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP04-A-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP04-A-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5041</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP04-A-POS2</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13241.86</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88152/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15300</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15300</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13241.86</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548105</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP06-POS2</MsgId> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15300</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03740</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03751</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03762</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03773</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03784</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-01</PmtInfId> + <InstrId>InstrId-BP06-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4060</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13246.19</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88153/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15305</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15305</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13246.19</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548122</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP06-POS2</MsgId> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15305</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03795</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="USD">1061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03806</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="USD">3061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03817</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="USD">4061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03828</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="USD">5061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP06-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03839</AcctSvcrRef> + <PmtInfId>PmtInfId-BP06-POS2-02</PmtInfId> + <InstrId>InstrId-BP06-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP06-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="USD">2061</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP06-POS2</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>ESSEGB2L</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13273.3</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88136/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15000</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13273.3</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488667</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP01-POS3</MsgId> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15000</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03840</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-01</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>111111111111111111111111110</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03851</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-02</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>222222222222222222222222222</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03862</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-03</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>333333333333333333333333334</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03873</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-04</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>444444444444444444444444444</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03884</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-01</PmtInfId> + <InstrId>InstrId-BP01-POS3-01-05</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5000</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>010643794</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>555555555555555555555555559</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13332.74</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88155/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">15405</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">15405</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13332.74</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.86548134</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP08-POS2</MsgId> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="USD">15405</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03895</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-01</EndToEndId> + <ChqNb>36501096</ChqNb> + </Refs> + <Amt Ccy="USD">1081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03906</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-02</EndToEndId> + <ChqNb>36501097</ChqNb> + </Refs> + <Amt Ccy="USD">2081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03917</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-03</EndToEndId> + <ChqNb>36501098</ChqNb> + </Refs> + <Amt Ccy="USD">3081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03928</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-04</EndToEndId> + <ChqNb>36501099</ChqNb> + </Refs> + <Amt Ccy="USD">4081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03939</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-02</PmtInfId> + <InstrId>InstrId-BP08-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-02-05</EndToEndId> + <ChqNb>36501100</ChqNb> + </Refs> + <Amt Ccy="USD">5081</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13361.79</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88138/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15100</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15100</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13361.79</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488675</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP02-POS2</MsgId> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15100</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03940</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03951</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03962</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03973</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03984</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-01</PmtInfId> + <InstrId>InstrId-BP02-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2020</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13406.04</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88140/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15150</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15150</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13406.04</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488713</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15150</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-03995</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-01</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-01</EndToEndId> + </Refs> + <Amt Ccy="CHF">1030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04006</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-02</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-02</EndToEndId> + </Refs> + <Amt Ccy="CHF">2030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04017</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-03</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-03</EndToEndId> + </Refs> + <Amt Ccy="CHF">3030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04028</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-04</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-04</EndToEndId> + </Refs> + <Amt Ccy="CHF">4030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04039</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-01</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-01-05</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-01-05</EndToEndId> + </Refs> + <Amt Ccy="CHF">5030</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5604835012345678009</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13414.89</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88142/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15160</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15160</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13414.89</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.8848872</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP03-B-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15160</TtlAmt> + </Btch> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13419.31</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88143/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15165</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15165</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13419.31</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488691</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP03-B-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15165</TtlAmt> + </Btch> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13627.26</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88154/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">15400</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">15400</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">13627.26</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.88488701</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP08-POS2</MsgId> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">15400</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04040</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-04</EndToEndId> + <ChqNb>36501094</ChqNb> + </Refs> + <Amt Ccy="CHF">4080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04051</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-03</EndToEndId> + <ChqNb>36501093</ChqNb> + </Refs> + <Amt Ccy="CHF">3080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04062</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-05</EndToEndId> + <ChqNb>36501095</ChqNb> + </Refs> + <Amt Ccy="CHF">5080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04073</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-01</EndToEndId> + <ChqNb>36501091</ChqNb> + </Refs> + <Amt Ccy="CHF">1080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP08-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04084</AcctSvcrRef> + <PmtInfId>PmtInfId-BP08-POS2-01</PmtInfId> + <InstrId>InstrId-BP08-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP08-POS2-01-02</EndToEndId> + <ChqNb>36501092</ChqNb> + </Refs> + <Amt Ccy="CHF">2080</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Creditor Name</Nm> + <PstlAdr> + <StrtNm>Street Name</StrtNm> + <BldgNb>4</BldgNb> + <PstCd>12345</PstCd> + <TwnNm>Town Name</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <Prtry> + <Tp>ChequeDeliverTo</Tp> + <Pty> + <Pty> + <Nm>Hans Meier</Nm> + </Pty> + </Pty> + </Prtry> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15055</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88137/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15055</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15055</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP01-POS3</MsgId> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15055</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04084</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-04</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>444444444444444444444444444</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04095</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-05</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>555555555555555555555555559</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04106</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-01</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>111111111111111111111111110</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04117</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-02</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>222222222222222222222222222</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP01-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04128</AcctSvcrRef> + <PmtInfId>PmtInfId-BP01-POS3-02</PmtInfId> + <InstrId>InstrId-BP01-POS3-02-03</InstrId> + <EndToEndId>EndToEndId-BP01-POS3-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3011</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP01-POS3</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>034567896</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>333333333333333333333333334</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15105</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88139/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15105</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15105</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP02-POS2</MsgId> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15105</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04139</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04140</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04151</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04162</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP02-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04173</AcctSvcrRef> + <PmtInfId>PmtInfId-BP02-POS2-02</PmtInfId> + <InstrId>InstrId-BP02-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP02-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2021</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP02-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <Othr> + <Id>700041528</Id> + </Othr> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>09000</MmbId> + </ClrSysMmbId> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15155</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88141/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15155</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15155</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15155</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04184</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-04</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04195</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-05</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04206</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-02</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04217</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-03</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP03-A-POS3</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04228</AcctSvcrRef> + <PmtInfId>PmtInfId-BP03-A-POS3-02</PmtInfId> + <InstrId>InstrId-BP03-A-POS3-02-01</InstrId> + <EndToEndId>EndToEndId-BP03-A-POS3-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1031</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH7304835833740032001</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15250</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88148/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15250</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15250</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15250</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04239</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04240</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04251</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04262</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04273</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3050</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15255</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88149/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15255</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15255</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15255</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04284</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04295</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04306</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04317</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-A-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04328</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-A-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-A-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP05-A-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2051</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-A-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15260</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88150/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15260</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15260</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15260</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04339</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-03</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04340</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-04</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04351</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-05</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04362</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-01</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04373</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-01</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-01-02</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-01-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2052</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">15265</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>DNTS-171127-CS-88151/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">15265</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">15265</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="EUR">15265</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-04384</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-04</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-04</EndToEndId> + </Refs> + <Amt Ccy="EUR">4053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0495</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-01</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-01</EndToEndId> + </Refs> + <Amt Ccy="EUR">1053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0506</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-03</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-03</EndToEndId> + </Refs> + <Amt Ccy="EUR">3053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0517</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-02</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-02</EndToEndId> + </Refs> + <Amt Ccy="EUR">2053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MsgId-BP05-B-POS2</MsgId> + <AcctSvcrRef>DNUC-191001-CS-0528</AcctSvcrRef> + <PmtInfId>PmtInfId-BP05-B-POS2-02</PmtInfId> + <InstrId>InstrId-BP05-B-POS2-02-05</InstrId> + <EndToEndId>EndToEndId-BP05-B-POS2-02-05</EndToEndId> + </Refs> + <Amt Ccy="EUR">5053</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Max Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>BP05-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGDDEFFXXX</BICFI> + <Nm>Creditor Agent Name</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">881.87</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36700/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">913.28889</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36700</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">1030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">883.59</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36739/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">915.06227</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36739</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">1032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">884.44</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36746/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">915.94896</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36746</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">1033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">900</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36835/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">1000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">900</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36835</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR11171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">900</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1738.06</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36701/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1799.97714</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36701</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">2030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1739.77</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36747/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1801.75052</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36747</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">2032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1740.63</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36748/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">1802.63721</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36748</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">2033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">1800</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36836/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">2000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">1800</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36836</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR12171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">1800</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2594.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36702/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2686.66539</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36702</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">3030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2595.96</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36749/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2688.43876</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36749</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">3032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2596.82</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36750/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2689.32545</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36750</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">3033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2654.18</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36830/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3100</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2654.18</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36830</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF117171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3100</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2700</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36839/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">3000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">2700</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49200</MsgId> + <AcctSvcrRef>80VA-171127-CS-36839</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49200</PmtInfId> + <EndToEndId>E2EPBP13-INEUR13171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">2700</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2739.8</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36831/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3200</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2739.8</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36831</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF127171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3200</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2825.42</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36832/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3300</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2825.42</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36832</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF137171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3300</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2911.04</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36833/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3400</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2911.04</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36833</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF147171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3400</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">2996.66</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36834/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3500</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">2996.66</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1679679</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49197</MsgId> + <AcctSvcrRef>80VA-171127-CS-36834</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49197</PmtInfId> + <EndToEndId>E2EBP12-INCHF157171127JB00</EndToEndId> + </Refs> + <Amt Ccy="CHF">3500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3450.44</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36703/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4030</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3573.35363</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49186</MsgId> + <AcctSvcrRef>80VA-171127-CS-36703</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49186</PmtInfId> + </Refs> + <Amt Ccy="CHF">4030</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-A-POS3</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3452.15</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36751/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4032</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3575.12701</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36751</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">4032</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3453.01</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36752/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">4033</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="EUR">3576.0137</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>1.1277921</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49188</MsgId> + <AcctSvcrRef>80VA-171127-CS-36752</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49188</PmtInfId> + </Refs> + <Amt Ccy="CHF">4033</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>BP03-B-POS2</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>OTHR</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>CRESCHZZ</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>MS03</Cd> + </Rsn> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">3600</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36837/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">4000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">3600</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36837</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR14171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">3600</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">4500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-11-27</Dt> + </BookgDt> + <ValDt> + <Dt>2022-11-27</Dt> + </ValDt> + <AcctSvcrRef>80VA-171127-CS-36838/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">5000</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">4500</Amt> + <CcyXchg> + <SrcCcy>CHF</SrcCcy> + <TrgtCcy>EUR</TrgtCcy> + <XchgRate>0.9</XchgRate> + <QtnDt>2022-11-27T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13S0-171127-MS-49199</MsgId> + <AcctSvcrRef>80VA-171127-CS-36838</AcctSvcrRef> + <PmtInfId>13S0-171127-MS-49199</PmtInfId> + <EndToEndId>E2EPBP13-INEUR15171127H00</EndToEndId> + </Refs> + <Amt Ccy="EUR">4500</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Debtor Name</Nm> + <PstlAdr> + <AdrLine>Adress Line 1</AdrLine> + <AdrLine>Adress Line 2</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="EUR">13273.3</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>PDNG</Cd> + </Sts> + <ValDt> + <Dt>2022-11-15</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-80769</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>1520</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>1520</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">220000000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>PDNG</Cd> + </Sts> + <ValDt> + <Dt>2022-11-22</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-90770</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8017</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8017</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="EUR">10000000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>PDNG</Cd> + </Sts> + <ValDt> + <Dt>2022-11-22</Dt> + </ValDt> + <AcctSvcrRef>DNSJ-171115-CS-90781</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8017</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8017</AddtlNtryInf> + </Ntry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/cs/camt.053_SIC_04_088583185407_ND_0885831854071000_20220323_010729778000_000.xml b/testbench/sample/cs/camt.053_SIC_04_088583185407_ND_0885831854071000_20220323_010729778000_000.xml @@ -0,0 +1,886 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.04"> +<BkToCstmrStmt> +<GrpHdr> +<MsgId>CAMT053_20220323_010729756_VJC7LIIF</MsgId> +<CreDtTm>2022-03-23T01:07:29.756Z</CreDtTm> +<MsgPgntn> +<PgNb>1</PgNb> +<LastPgInd>true</LastPgInd> +</MsgPgntn> +<AddtlInf>SPS/1.7/PROD</AddtlInf> +</GrpHdr> +<Stmt> +<Id>cbe792bcaaf74a87b6c5c0c77df10872</Id> +<ElctrncSeqNb>58</ElctrncSeqNb> +<CreDtTm>2022-03-23T01:07:29.778Z</CreDtTm> +<FrToDt> +<FrDtTm>2022-03-22T00:00:00+01:00</FrDtTm> +<ToDtTm>2022-03-22T23:59:00+01:00</ToDtTm> +</FrToDt> +<Acct> +<Id> +<Othr> +<Id>0885831854071000</Id> +</Othr> +</Id> +<Ccy>CHF</Ccy> +<Ownr> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<AdrLine>Zürich</AdrLine> +</PstlAdr> +</Ownr> +<Svcr> +<FinInstnId> +<BICFI>CRESCHZZ80A</BICFI> +<Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> +<Othr> +<Id>CHE-116.285.487 MWST</Id> +<Issr>VAT-ID</Issr> +</Othr> +</FinInstnId> +</Svcr> +</Acct> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>OPBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">7751.38</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-03-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>FWAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-03-23</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">19273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-03-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-03-22</Dt> +</Dt> +</Bal> +<TxsSummry> +<TtlNtries> +<NbOfNtries>17</NbOfNtries> +<Sum>18258.18</Sum> +<TtlNetNtry> +<Amt>17521.96</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +</TtlNetNtry> +</TtlNtries> +<TtlCdtNtries> +<NbOfNtries>9</NbOfNtries> +<Sum>17890.07</Sum> +</TtlCdtNtries> +<TtlDbtNtries> +<NbOfNtries>8</NbOfNtries> +<Sum>368.11</Sum> +</TtlDbtNtries> +</TxsSummry> +<Ntry> +<Amt Ccy="CHF">2.36</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43783/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="EUR">2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="EUR">2</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">2.36</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.18</XchgRate> +<QtnDt>2022-03-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0150D4D8E71C447EBF774FB84E1F7946</MsgId> +<PmtInfId>BLVL-1-18032208215187</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="EUR">2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">4.78</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58740/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">5</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">5</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">4.78</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95611387</XchgRate> +<QtnDt>2022-03-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">5</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> +<PmtInfId>BLVL-1-18032208093429</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">5</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">9.57</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43962/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">10</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">10</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">9.57</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95711254</XchgRate> +<QtnDt>2022-03-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">23</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +<Rcrd> +<Amt Ccy="CHF">18</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>EXTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> +<PmtInfId>BLVL-1-18032208261993</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">10</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58062/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0D6E675AB5794B5BA889A0CCEAAD1D16</MsgId> +<PmtInfId>BLVL-1-18032207545645</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.2</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40797/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.2</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> +<PmtInfId>BLVL-1-18032207590104</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNWL-180322-CS-87851/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>BOOK</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">100</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">100</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>57af4bcfda8d4f8fb958c5424d73c12e</MsgId> +<AcctSvcrRef>DNWL-180322-CS-87851</AcctSvcrRef> +<PmtInfId>DNCS-20220322-IXN0</PmtInfId> +<InstrId>DNCS-20220322-IXN0-TXN0</InstrId> +<EndToEndId>SP-57273905-0</EndToEndId> +</Refs> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Nm>Barbara Muster, Zürich</Nm> +<PstlAdr> +<AdrLine>Barbara Muster, Zürich</AdrLine> +</PstlAdr> +</Cdtr> +<CdtrAcct> +<Id> +<IBAN>CH3704835833740031000</IBAN> +</Id> +</CdtrAcct> +</RltdPties> +<RltdAgts> +<CdtrAgt> +<FinInstnId> +<ClrSysMmbId> +<ClrSysId> +<Cd>CHBCC</Cd> +</ClrSysId> +<MmbId>04835</MmbId> +</ClrSysMmbId> +<Nm>Credit Suisse (Schweiz) AG</Nm> +<PstlAdr> +<AdrLine>Paradeplatz 8</AdrLine> +<AdrLine>8070 Zürich CH</AdrLine> +</PstlAdr> +</FinInstnId> +</CdtrAgt> +</RltdAgts> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">120</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40193/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">120</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">120</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> +<PmtInfId>BLVL-1-18032207463420</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">120</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">111.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>DNRD-180323-CS-75599/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">111.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">111.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> +<PmtInfId>BLVL-1-19030708451663</PmtInfId> +<NbOfTxs>2</NbOfTxs> +<TtlAmt Ccy="CHF">111.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.8</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222247667/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.03.18</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>80WL-180322-CS-55958/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TF-180322-MS-85571</MsgId> +<AcctSvcrRef>80WL-180322-CS-55958</AcctSvcrRef> +<PmtInfId>13TF-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 23456</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3.47</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>80WR-180322-CS-15197/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>ESCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="EUR">3</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">3.47</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.15632286</XchgRate> +<QtnDt>2022-03-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TL-180322-MS-32279</MsgId> +<AcctSvcrRef>80WR-180322-CS-15197</AcctSvcrRef> +<PmtInfId>13TL-180322-MS-32279</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="EUR">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Nm>KOWALSKI JAN</Nm> +<PstlAdr> +<Ctry>PL</Ctry> +<AdrLine>SZCZYTNICKA 9</AdrLine> +<AdrLine>PL WROCLAW</AdrLine> +</PstlAdr> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>Invoice 45678</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-23</Dt> +</ValDt> +<AcctSvcrRef>08922018031005244600/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">6000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>31XY-180322-MS-85571</MsgId> +<AcctSvcrRef>91AB-180322-CS-55958</AcctSvcrRef> +<PmtInfId>31XY-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 67890</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>true</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>80WE-180321-CS-53986/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>RRTN</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TJ-180321-MS-42880</MsgId> +<AcctSvcrRef>80WE-180321-CS-53986</AcctSvcrRef> +<PmtInfId>13TJ-180321-MS-42880</PmtInfId> +<EndToEndId>ETE68E82E7E701E4DB2B838318A8BA551CF</EndToEndId> +</Refs> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<PstCd>8001</PstCd> +<TwnNm>Zuerich</TwnNm> +</PstlAdr> +</Cdtr> +</RltdPties> +<RtrInf> +<OrgnlBkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</OrgnlBkTxCd> +<Orgtr> +<Id> +<OrgId> +<AnyBIC>UBSWCHZH80A</AnyBIC> +</OrgId> +</Id> +</Orgtr> +<Rsn> +<Cd>NARR</Cd> +</Rsn> +<AddtlInf>RETOUR SIC VAL 22.03.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH</AddtlInf> +<AddtlInf>/SETT/2022-03-22T15:52:42</AddtlInf> +</RtrInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.75</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222252626/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.03.18</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">7761.35</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000075/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000075</MsgId> +<NbOfTxs>5</NbOfTxs> +<TtlAmt Ccy="CHF">7761.35</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 999999</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">119.45</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-21</Dt> +</ValDt> +<AcctSvcrRef>4BA02002068000015/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA02002068000015</MsgId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">119.45</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 901709</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>CH4531000831854071000</NtryRef> +<Amt Ccy="CHF">997.25</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts>BOOK</Sts> +<BookgDt> +<Dt>2022-03-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-03-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000076/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>VCOM</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000076</MsgId> +<NbOfTxs>5</NbOfTxs> +<TtlAmt Ccy="CHF">997.25</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +</Ntry> +</Stmt> +</BkToCstmrStmt> +</Document> +\ No newline at end of file diff --git a/testbench/sample/cs/camt.053_SIC_04_088583185407_WD_0885831854071000_20220323_010729778000_000.xml b/testbench/sample/cs/camt.053_SIC_04_088583185407_WD_0885831854071000_20220323_010729778000_000.xml @@ -0,0 +1,1384 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.04"> + <BkToCstmrStmt> + <GrpHdr> + <MsgId>CAMT053_20221223_010729756_VJC7LIIF</MsgId> + <CreDtTm>2022-12-23T01:07:29.756Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.7/PROD</AddtlInf> + </GrpHdr> + <Stmt> + <Id>cbe792bcaaf74a87b6c5c0c77df10872</Id> + <ElctrncSeqNb>58</ElctrncSeqNb> + <CreDtTm>2022-12-23T01:07:29.778Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-12-22T00:00:00+01:00</FrDtTm> + <ToDtTm>2022-12-22T23:59:00+01:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <Othr> + <Id>0885831854071000</Id> + </Othr> + </Id> + <Ccy>CHF</Ccy> + <Ownr> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <AdrLine>Zürich</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">7751.38</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>FWAV</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">25153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-23</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>CLAV</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">19153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>CLBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">25153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>16</NbOfNtries> + <Sum>18138.73</Sum> + <TtlNetNtry> + <Amt>17402.51</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>8</NbOfNtries> + <Sum>17770.62</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>8</NbOfNtries> + <Sum>368.11</Sum> + </TtlDbtNtries> + </TxsSummry> + <Ntry> + <Amt Ccy="CHF">2.36</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-43783/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">2</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">2</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">2.36</Amt> + <CcyXchg> + <SrcCcy>EUR</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>1.18</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MSG0150D4D8E71C447EBF774FB84E1F7946</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43783</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208215187</PmtInfId> + <InstrId>CLVL-1-18032711450502-1</InstrId> + <EndToEndId>ETEF9123BE97B2243629A9CF12FC6B6B80D</EndToEndId> + </Refs> + <Amt Ccy="EUR">2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Nm>Barbara Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Jan Kowalski</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>Szczytnicka 9</AdrLine> + <AdrLine>50-382 Wroclaw</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>PL79105015751000002345678901</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGBPLPW</BICFI> + <Nm>ING BANK SLASKI SA</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>UL. SOKOLSKA 34 40-086 KATOWICE </AdrLine> + <AdrLine>PL</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">4.78</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQN-180322-CS-58740/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">4.78</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>0.95611387</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">5</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> + <PmtInfId>BLVL-1-18032208093429</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="USD">5</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43794</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208093429</PmtInfId> + <InstrId>CLVL-1-18032711020928-1</InstrId> + <EndToEndId>ETE6A71EE9E18FF485EAC881A3B2E93475A</EndToEndId> + </Refs> + <Amt Ccy="USD">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Nm>Barbara Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period + taking into account the product-specific terms and conditions.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">9.57</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-43962/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">10</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">10</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">9.57</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>0.95711254</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">23</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + <Rcrd> + <Amt Ccy="CHF">18</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>EXTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> + <PmtInfId>BLVL-1-18032208261993</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="USD">10</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43705</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208261993</PmtInfId> + <InstrId>CLVL-1-18032711084266-1</InstrId> + <EndToEndId>ETE1B58D1C4D44F4D75A481832C36D54D3E</EndToEndId> + </Refs> + <Amt Ccy="USD">10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Nm>Barbara Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Jan Kowalski</Nm> + <PstlAdr> + <StrtNm>Szczytnicka 9</StrtNm> + <PstCd>50-382</PstCd> + <TwnNm>Wroclaw</TwnNm> + <Ctry>PL</Ctry> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>PL79105015751000002345678901</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGBPLPW</BICFI> + <Nm>ING BANK SLASKI SA</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>UL. SOKOLSKA 34 40-086 KATOWICE </AdrLine> + <AdrLine>PL</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Invoice AB-123-C</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period + taking into account the product-specific terms and conditions.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">10.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQN-180322-CS-58062/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">10.1</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">10.1</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MSG0D6E675AB5794B5BA889A0CCEAAD1D16</MsgId> + <AcctSvcrRef>DNQN-180322-CS-58062</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207545645</PmtInfId> + <InstrId>5139/180314/1ABC</InstrId> + <EndToEndId>5139/180314/1ABC</EndToEndId> + </Refs> + <Amt Ccy="CHF">10.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Seefeldstrasse 1</AdrLine> + <AdrLine>8008 Zurich</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Rechnungsnummer 18C527-005</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">10.2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-40797/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">10.2</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">10.2</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> + <PmtInfId>BLVL-1-18032207590104</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="CHF">10.2</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43716</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207590104</PmtInfId> + <InstrId>CLVL-1-18032710592518-1</InstrId> + <EndToEndId>ETE53005D7923CD49509A3E7DB9BEC094A9</EndToEndId> + </Refs> + <Amt Ccy="CHF">10.2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Nm>Barbara Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNWL-180322-CS-87851/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>BOOK</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">100</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">100</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>57af4bcfda8d4f8fb958c5424d73c12e</MsgId> + <AcctSvcrRef>DNWL-180322-CS-87851</AcctSvcrRef> + <PmtInfId>DNCS-20220322-IXN0</PmtInfId> + <InstrId>DNCS-20220322-IXN0-TXN0</InstrId> + <EndToEndId>SP-57273905-0</EndToEndId> + </Refs> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>Barbara Muster, Zürich</Nm> + <PstlAdr> + <AdrLine>Barbara Muster, Zürich</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Paradeplatz 8</AdrLine> + <AdrLine>8070 Zürich CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-40193/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">120</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">120</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> + <PmtInfId>BLVL-1-18032207463420</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="CHF">120</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43727</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207463420</PmtInfId> + <InstrId>CLVL-1-18032710510965-1</InstrId> + <EndToEndId>ETEE529F052BD2B4C8B85F345FC543B4930</EndToEndId> + </Refs> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <UltmtDbtr> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <StrtNm>Hauptstrasse 1</StrtNm> + <PstCd>8001</PstCd> + <TwnNm>Zürich</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </UltmtDbtr> + <Cdtr> + <Nm>Aero Club der Schweiz</Nm> + <PstlAdr> + <AdrLine>Lidostrasse 5</AdrLine> + <AdrLine>6006 Luzern</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH0930778123456789000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00778</MmbId> + </ClrSysMmbId> + <Nm>Luzerner Kantonalbank AG</Nm> + <PstlAdr> + <AdrLine>Pilatusstrasse 12</AdrLine> + <AdrLine>6002 Luzern CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>047280000701047470007679672</Ref> + </CdtrRefInf> + <AddtlRmtInf>Aero Club der Schweiz</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">111.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNRD-180323-CS-75599/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">111.1</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">111.1</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <NbOfTxs>2</NbOfTxs> + <TtlAmt Ccy="CHF">111.1</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43738</AcctSvcrRef> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <InstrId>CLVL-1-19030708451663-1</InstrId> + <EndToEndId>ETE29CDDA854EE2484ABEF9DE87A81E0C8F</EndToEndId> + </Refs> + <Amt Ccy="CHF">11.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Nm>Barbara Muster</Nm> + </InitgPty> + <Cdtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43749</AcctSvcrRef> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <InstrId>CLVL-1-19030708451663-2</InstrId> + <EndToEndId>ETE241D2750BC49461AAE9A98093F458940</EndToEndId> + </Refs> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <UltmtDbtr> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <StrtNm>Hauptstrasse 1</StrtNm> + <PstCd>8001</PstCd> + <TwnNm>Zürich</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </UltmtDbtr> + <Cdtr> + <Nm>Aero Club der Schweiz</Nm> + <PstlAdr> + <AdrLine>Lidostrasse 5</AdrLine> + <AdrLine>6006 Luzern</AdrLine> + </PstlAdr> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH0930778123456789000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00778</MmbId> + </ClrSysMmbId> + <Nm>Luzerner Kantonalbank AG</Nm> + <PstlAdr> + <AdrLine>Pilatusstrasse 12</AdrLine> + <AdrLine>6002 Luzern CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>047280000701047470007679688</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">2.8</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>08351803222247667/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8037</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG + 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WL-180322-CS-55958/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TF-180322-MS-85571</MsgId> + <AcctSvcrRef>80WL-180322-CS-55958</AcctSvcrRef> + <PmtInfId>13TF-180322-MS-85571</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + </Refs> + <Amt Ccy="CHF">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>BARBARA MUSTER</Nm> + <PstlAdr> + <AdrLine>8001 ZURICH</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>RECHNUNG 23456</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3.47</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WR-180322-CS-15197/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">3</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">3.47</Amt> + <CcyXchg> + <SrcCcy>EUR</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>1.15632286</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TL-180322-MS-32279</MsgId> + <AcctSvcrRef>80WR-180322-CS-15197</AcctSvcrRef> + <PmtInfId>13TL-180322-MS-32279</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + </Refs> + <Amt Ccy="EUR">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>KOWALSKI JAN</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>SZCZYTNICKA 9</AdrLine> + <AdrLine>PL WROCLAW</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>Invoice 45678</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">6000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-23</Dt> + </ValDt> + <AcctSvcrRef>08922018031005244600/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">6000</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>31XY-180322-MS-85571</MsgId> + <AcctSvcrRef>91AB-180322-CS-55958</AcctSvcrRef> + <PmtInfId>31XY-180322-MS-85571</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + </Refs> + <Amt Ccy="CHF">6000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>BARBARA MUSTER</Nm> + <PstlAdr> + <AdrLine>8001 ZURICH</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>RECHNUNG 67890</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WE-180321-CS-53986/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3000</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TJ-180321-MS-42880</MsgId> + <AcctSvcrRef>80WE-180321-CS-53986</AcctSvcrRef> + <PmtInfId>13TJ-180321-MS-42880</PmtInfId> + <EndToEndId>ETE68E82E7E701E4DB2B838318A8BA551CF</EndToEndId> + </Refs> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <PstCd>8001</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>UBSWCHZH80A</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>NARR</Cd> + </Rsn> + <AddtlInf>RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH</AddtlInf> + <AddtlInf>/SETT/2022-12-22T15:52:42</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">2.75</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>08351803222252626/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8037</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL + WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am + 22.12.22</AddtlNtryInf> + </Ntry> + <Ntry> + <NtryRef>010026540</NtryRef> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80UL-171123-CS-35153/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">7761.35</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13RG-171123-MS-49259</MsgId> + <AcctSvcrRef>80UL-171123-CS-35153</AcctSvcrRef> + <PmtInfId>13RG-171123-MS-49259</PmtInfId> + <EndToEndId>E2EBP11-ESR12171123</EndToEndId> + </Refs> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Bundesplatz 1</AdrLine> + <AdrLine>3003 Bern</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999111122233344455678805</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?21010026540 999999</AddtlNtryInf> + </Ntry> + <Ntry> + <NtryRef>CH4531000831854071000</NtryRef> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80UL171123CS35154/1001</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">997.25</Amt> + </TxAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13RG-171123-MS-49260</MsgId> + <AcctSvcrRef>80UL-171123-CS-35154</AcctSvcrRef> + <PmtInfId>13RG-171123-MS-49260</PmtInfId> + <EndToEndId>E2EBP11-ESR12171124</EndToEndId> + </Refs> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Bundesplatz 1</AdrLine> + <AdrLine>3003 Bern</AdrLine> + </PstlAdr> + </Dbtr> + <UltmtDbtr> + <Nm>Pia-Maria Rutschmann-Schnyder</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Grosse Marktgasse 28</AdrLine> + <AdrLine>9400 Rorschach</AdrLine> + </PstlAdr> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999111122233344455678805</Ref> + </CdtrRefInf> + <AddtlRmtInf>Manuelle Bemerkung</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Stmt> + </BkToCstmrStmt> +</Document> diff --git a/testbench/sample/cs/camt.053_SPS_08_088583185407_DC_0885831854071000_20221223_010729778_000.xml b/testbench/sample/cs/camt.053_SPS_08_088583185407_DC_0885831854071000_20221223_010729778_000.xml @@ -0,0 +1,1084 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08"> +<BkToCstmrStmt> +<GrpHdr> +<MsgId>CAMT053_20221223_010729756_VJC7LIIF</MsgId> +<CreDtTm>2022-12-23T01:07:29.756Z</CreDtTm> +<MsgPgntn> +<PgNb>1</PgNb> +<LastPgInd>true</LastPgInd> +</MsgPgntn> +<AddtlInf>SPS/2.0/PROD</AddtlInf> +</GrpHdr> +<Stmt> +<Id>cbe792bcaaf74a87b6c5c0c77df10872</Id> +<ElctrncSeqNb>58</ElctrncSeqNb> +<CreDtTm>2022-12-23T01:07:29.778Z</CreDtTm> +<FrToDt> +<FrDtTm>2022-12-22T00:00:00+01:00</FrDtTm> +<ToDtTm>2022-12-22T23:59:00+01:00</ToDtTm> +</FrToDt> +<Acct> +<Id> +<Othr> +<Id>0885831854071000</Id> +</Othr> +</Id> +<Ccy>CHF</Ccy> +<Ownr> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<AdrLine>Zürich</AdrLine> +</PstlAdr> +</Ownr> +<Svcr> +<FinInstnId> +<BICFI>CRESCHZZ80A</BICFI> +<Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> +<Othr> +<Id>CHE-116.285.487 MWST</Id> +<Issr>VAT-ID</Issr> +</Othr> +</FinInstnId> +</Svcr> +</Acct> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>OPBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">7751.38</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>FWAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-23</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">19273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<TxsSummry> +<TtlNtries> +<NbOfNtries>17</NbOfNtries> +<Sum>18258.18</Sum> +<TtlNetNtry> +<Amt>17521.96</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +</TtlNetNtry> +</TtlNtries> +<TtlCdtNtries> +<NbOfNtries>9</NbOfNtries> +<Sum>17890.07</Sum> +</TtlCdtNtries> +<TtlDbtNtries> +<NbOfNtries>8</NbOfNtries> +<Sum>368.11</Sum> +</TtlDbtNtries> +</TxsSummry> +<Ntry> +<Amt Ccy="CHF">2.36</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43783/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="EUR">2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="EUR">2</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">2.36</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.18</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0150D4D8E71C447EBF774FB84E1F7946</MsgId> +<PmtInfId>BLVL-1-18032208215187</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="EUR">2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">4.78</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58740/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">5</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">5</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">4.78</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95611387</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">5</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> +<PmtInfId>BLVL-1-18032208093429</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">5</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">9.57</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43962/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">10</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">10</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">9.57</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95711254</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">23</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +<Rcrd> +<Amt Ccy="CHF">18</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>EXTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> +<PmtInfId>BLVL-1-18032208261993</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">10</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58062/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0D6E675AB5794B5BA889A0CCEAAD1D16</MsgId> +<PmtInfId>BLVL-1-18032207545645</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.2</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40797/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.2</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> +<PmtInfId>BLVL-1-18032207590104</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNWL-180322-CS-87851/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>BOOK</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">100</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">100</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>57af4bcfda8d4f8fb958c5424d73c12e</MsgId> +<AcctSvcrRef>DNWL-221222-CS-87851</AcctSvcrRef> +<PmtInfId>DNCS-20221222-IXN0</PmtInfId> +<InstrId>DNCS-20221222-IXN0-TXN0</InstrId> +<EndToEndId>SP-57273905-0</EndToEndId> +</Refs> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Pty> +<Nm>Barbara Muster, Zürich</Nm> +<PstlAdr> +<AdrLine>Barbara Muster, Zürich</AdrLine> +</PstlAdr> +</Pty> +</Cdtr> +<CdtrAcct> +<Id> +<IBAN>CH3704835833740031000</IBAN> +</Id> +</CdtrAcct> +</RltdPties> +<RltdAgts> +<CdtrAgt> +<FinInstnId> +<ClrSysMmbId> +<ClrSysId> +<Cd>CHBCC</Cd> +</ClrSysId> +<MmbId>04835</MmbId> +</ClrSysMmbId> +<Nm>Credit Suisse (Schweiz) AG</Nm> +<PstlAdr> +<AdrLine>Paradeplatz 8</AdrLine> +<AdrLine>8070 Zürich CH</AdrLine> +</PstlAdr> +</FinInstnId> +</CdtrAgt> +</RltdAgts> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">120</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40193/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">120</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">120</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> +<PmtInfId>BLVL-1-18032207463420</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">120</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">111.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNRD-180323-CS-75599/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">111.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">111.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> +<PmtInfId>BLVL-1-19030708451663</PmtInfId> +<NbOfTxs>2</NbOfTxs> +<TtlAmt Ccy="CHF">111.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.8</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222247667/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WL-180322-CS-55958/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TF-180322-MS-85571</MsgId> +<AcctSvcrRef>80WL-180322-CS-55958</AcctSvcrRef> +<PmtInfId>13TF-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 23456</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3.47</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WR-180322-CS-15197/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>ESCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="EUR">3</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">3.47</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.15632286</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TL-180322-MS-32279</MsgId> +<AcctSvcrRef>80WR-180322-CS-15197</AcctSvcrRef> +<PmtInfId>13TL-180322-MS-32279</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="EUR">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>KOWALSKI JAN</Nm> +<PstlAdr> +<Ctry>PL</Ctry> +<AdrLine>SZCZYTNICKA 9</AdrLine> +<AdrLine>PL WROCLAW</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>Invoice 45678</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-23</Dt> +</ValDt> +<AcctSvcrRef>08922018031005244600/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">6000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>31XY-180322-MS-85571</MsgId> +<AcctSvcrRef>91AB-180322-CS-55958</AcctSvcrRef> +<PmtInfId>31XY-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 67890</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>true</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WE-180321-CS-53986/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>RRTN</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TJ-180321-MS-42880</MsgId> +<AcctSvcrRef>80WE-180321-CS-53986</AcctSvcrRef> +<PmtInfId>13TJ-180321-MS-42880</PmtInfId> +<EndToEndId>ETE68E82E7E701E4DB2B838318A8BA551CF</EndToEndId> +</Refs> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Pty> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<PstCd>8001</PstCd> +<TwnNm>Zuerich</TwnNm> +</PstlAdr> +</Pty> +</Cdtr> +</RltdPties> +<RtrInf> +<OrgnlBkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</OrgnlBkTxCd> +<Orgtr> +<Id> +<OrgId> +<AnyBIC>UBSWCHZH80A</AnyBIC> +</OrgId> +</Id> +</Orgtr> +<Rsn> +<Cd>NARR</Cd> +</Rsn> +<AddtlInf>RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH</AddtlInf> +<AddtlInf>/SETT/2022-12-22T15:52:42</AddtlInf> +</RtrInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.75</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222252626/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.12.22</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">7761.35</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000075/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000075</MsgId> +<NbOfTxs>5</NbOfTxs> +<TtlAmt Ccy="CHF">7761.35</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 999999</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">119.45</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-21</Dt> +</ValDt> +<AcctSvcrRef>4BA02002068000015/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA02002068000015</MsgId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">119.45</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 901709</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>CH4531000831854071000</NtryRef> +<Amt Ccy="CHF">997.25</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000076/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>VCOM</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">0.20</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">0.20</Amt> +<ChrgInclInd>false</ChrgInclInd> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000076</MsgId> +<NbOfTxs>2</NbOfTxs> +<TtlAmt Ccy="CHF">997.25</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +<TxDtls> +<Refs> +<MsgId>13RG-171123-MS-49260</MsgId> +<AcctSvcrRef>80UL-171123-CS-35154</AcctSvcrRef> +<PmtInfId>13RG-171123-MS-49260</PmtInfId> +<EndToEndId>123456789123456789ACE</EndToEndId> +<UETR>eb6305c9-1f7f-49de-aed0-16487c27b42d</UETR> +<TxId>0233458UP0198446</TxId> +</Refs> +<Amt Ccy="CHF">900.00</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">900.00</Amt> +</TxAmt> +</AmtDtls> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>VCOM</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">0.10</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +<Rate>1.00000</Rate> +<Br>DEBT</Br> +</Rcrd> +</Chrgs> +<RltdPties> +<Dbtr> +<Pty> +<Nm>Max Muster</Nm> +<PstlAdr> +<AdrLine>Bundesplatz 1 3003 Bern</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +<UltmtDbtr> +<Pty> +<Nm>Pia-Maria Rutschmann-Schnyder</Nm> +<PstlAdr> +<Ctry>CH</Ctry> +<AdrLine>Grosse Marktgasse 28</AdrLine> +<AdrLine>9400 Rorschach</AdrLine> +</PstlAdr> +</Pty> +</UltmtDbtr> +</RltdPties> +<RmtInf> +<Strd> +<CdtrRefInf> +<Tp> +<CdOrPrtry> +<Prtry>QRR</Prtry> +</CdOrPrtry> +</Tp> +<Ref>000000000000000000000000034</Ref> +</CdtrRefInf> +<AddtlRmtInf>FREE TEXT</AddtlRmtInf> +</Strd> +</RmtInf> +</TxDtls> +<TxDtls> +<Refs> +<MsgId>24RG-182123-MS-49280</MsgId> +<AcctSvcrRef>81UL-172223-CS-35164</AcctSvcrRef> +<PmtInfId>24RG-182123-MS-49280</PmtInfId> +<EndToEndId>23456789123456789ACE2</EndToEndId> +<UETR>84eed956-57c0-4c39-b2d3-66d6dad93a68</UETR> +<TxId>1223457TO9086198</TxId> +</Refs> +<Amt Ccy="CHF">97.25</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">97.25</Amt> +</TxAmt> +</AmtDtls> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>VCOM</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">0.10</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +<Rate>1.00000</Rate> +<Br>DEBT</Br> +</Rcrd> +</Chrgs> +<RltdPties> +<Dbtr> +<Pty> +<Nm>SARAH DUPONT</Nm> +<PstlAdr> +<AdrLine>LANDSTRASSE 334 CH 3280 MURTEN</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +<UltmtDbtr> +<Pty> +<Nm>Roland Dupont</Nm> +<PstlAdr> +<Ctry>CH</Ctry> +<AdrLine>Landstrasse 334</AdrLine> +<AdrLine>3280 Murten</AdrLine> +</PstlAdr> +</Pty> +</UltmtDbtr> +</RltdPties> +<RmtInf> +<Strd> +<CdtrRefInf> +<Tp><CdOrPrtry> +<Prtry>QRR</Prtry> +</CdOrPrtry> +</Tp> +<Ref>000000000000000000000000026</Ref> +</CdtrRefInf> +<AddtlRmtInf>RANDOM TEXT</AddtlRmtInf> +</Strd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +</Stmt> +</BkToCstmrStmt> +</Document> +\ No newline at end of file diff --git a/testbench/sample/cs/camt.053_SPS_08_088583185407_ND_0885831854071000_20221223_010729778000.xml b/testbench/sample/cs/camt.053_SPS_08_088583185407_ND_0885831854071000_20221223_010729778000.xml @@ -0,0 +1,930 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08"> +<BkToCstmrStmt> +<GrpHdr> +<MsgId>CAMT053_20221223_010729756_VJC7LIIF</MsgId> +<CreDtTm>2022-12-23T01:07:29.756Z</CreDtTm> +<MsgPgntn> +<PgNb>1</PgNb> +<LastPgInd>true</LastPgInd> +</MsgPgntn> +<AddtlInf>SPS/2.0/PROD</AddtlInf> +</GrpHdr> +<Stmt> +<Id>cbe792bcaaf74a87b6c5c0c77df10872</Id> +<ElctrncSeqNb>58</ElctrncSeqNb> +<CreDtTm>2022-12-23T01:07:29.778Z</CreDtTm> +<FrToDt> +<FrDtTm>2022-12-22T00:00:00+01:00</FrDtTm> +<ToDtTm>2022-12-22T23:59:00+01:00</ToDtTm> +</FrToDt> +<Acct> +<Id> +<Othr> +<Id>0885831854071000</Id> +</Othr> +</Id> +<Ccy>CHF</Ccy> +<Ownr> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<AdrLine>Zürich</AdrLine> +</PstlAdr> +</Ownr> +<Svcr> +<FinInstnId> +<BICFI>CRESCHZZ80A</BICFI> +<Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> +<Othr> +<Id>CHE-116.285.487 MWST</Id> +<Issr>VAT-ID</Issr> +</Othr> +</FinInstnId> +</Svcr> +</Acct> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>OPBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">7751.38</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>FWAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-23</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLAV</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">19273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<Bal> +<Tp> +<CdOrPrtry> +<Cd>CLBD</Cd> +</CdOrPrtry> +</Tp> +<Amt Ccy="CHF">25273.34</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Dt> +<Dt>2022-12-22</Dt> +</Dt> +</Bal> +<TxsSummry> +<TtlNtries> +<NbOfNtries>17</NbOfNtries> +<Sum>18258.18</Sum> +<TtlNetNtry> +<Amt>17521.96</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +</TtlNetNtry> +</TtlNtries> +<TtlCdtNtries> +<NbOfNtries>9</NbOfNtries> +<Sum>17890.07</Sum> +</TtlCdtNtries> +<TtlDbtNtries> +<NbOfNtries>8</NbOfNtries> +<Sum>368.11</Sum> +</TtlDbtNtries> +</TxsSummry> +<Ntry> +<Amt Ccy="CHF">2.36</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43783/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="EUR">2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="EUR">2</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">2.36</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.18</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0150D4D8E71C447EBF774FB84E1F7946</MsgId> +<PmtInfId>BLVL-1-18032208215187</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="EUR">2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">4.78</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58740/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">5</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">5</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">4.78</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95611387</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">5</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> +<PmtInfId>BLVL-1-18032208093429</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">5</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">9.57</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-43962/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="USD">10</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="USD">10</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">9.57</Amt> +<CcyXchg> +<SrcCcy>USD</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>0.95711254</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<Chrgs> +<TtlChrgsAndTaxAmt Ccy="CHF">23</TtlChrgsAndTaxAmt> +<Rcrd> +<Amt Ccy="CHF">5</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>INTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +<Rcrd> +<Amt Ccy="CHF">18</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<ChrgInclInd>false</ChrgInclInd> +<Tp> +<Prtry> +<Id>EXTERNAL</Id> +</Prtry> +</Tp> +</Rcrd> +</Chrgs> +<NtryDtls> +<Btch> +<MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> +<PmtInfId>BLVL-1-18032208261993</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="USD">10</TtlAmt> +</Btch> +</NtryDtls> +<AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQN-180322-CS-58062/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG0D6E675AB5794B5BA889A0CCEAAD1D16</MsgId> +<PmtInfId>BLVL-1-18032207545645</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">10.2</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40797/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">10.2</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">10.2</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> +<PmtInfId>BLVL-1-18032207590104</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">10.2</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNWL-180322-CS-87851/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>BOOK</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">100</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">100</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>57af4bcfda8d4f8fb958c5424d73c12e</MsgId> +<AcctSvcrRef>DNWL-221222-CS-87851</AcctSvcrRef> +<PmtInfId>DNCS-20221222-IXN0</PmtInfId> +<InstrId>DNCS-20221222-IXN0-TXN0</InstrId> +<EndToEndId>SP-57273905-0</EndToEndId> +</Refs> +<Amt Ccy="CHF">100</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Pty> +<Nm>Barbara Muster, Zürich</Nm> +<PstlAdr> +<AdrLine>Barbara Muster, Zürich</AdrLine> +</PstlAdr> +</Pty> +</Cdtr> +<CdtrAcct> +<Id> +<IBAN>CH3704835833740031000</IBAN> +</Id> +</CdtrAcct> +</RltdPties> +<RltdAgts> +<CdtrAgt> +<FinInstnId> +<ClrSysMmbId> +<ClrSysId> +<Cd>CHBCC</Cd> +</ClrSysId> +<MmbId>04835</MmbId> +</ClrSysMmbId> +<Nm>Credit Suisse (Schweiz) AG</Nm> +<PstlAdr> +<AdrLine>Paradeplatz 8</AdrLine> +<AdrLine>8070 Zürich CH</AdrLine> +</PstlAdr> +</FinInstnId> +</CdtrAgt> +</RltdAgts> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">120</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNQR-180322-CS-40193/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">120</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">120</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> +<PmtInfId>BLVL-1-18032207463420</PmtInfId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">120</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">111.1</Amt> +<CdtDbtInd>DBIT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>DNRD-180323-CS-75599/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>AUTT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<InstdAmt> +<Amt Ccy="CHF">111.1</Amt> +</InstdAmt> +<TxAmt> +<Amt Ccy="CHF">111.1</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<Btch> +<MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> +<PmtInfId>BLVL-1-19030708451663</PmtInfId> +<NbOfTxs>2</NbOfTxs> +<TtlAmt Ccy="CHF">111.1</TtlAmt> +</Btch> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.8</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222247667/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22</AddtlNtryInf> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WL-180322-CS-55958/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TF-180322-MS-85571</MsgId> +<AcctSvcrRef>80WL-180322-CS-55958</AcctSvcrRef> +<PmtInfId>13TF-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 23456</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3.47</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WR-180322-CS-15197/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>ESCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="EUR">3</Amt> +</TxAmt> +<CntrValAmt> +<Amt Ccy="CHF">3.47</Amt> +<CcyXchg> +<SrcCcy>EUR</SrcCcy> +<TrgtCcy>CHF</TrgtCcy> +<XchgRate>1.15632286</XchgRate> +<QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> +</CcyXchg> +</CntrValAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TL-180322-MS-32279</MsgId> +<AcctSvcrRef>80WR-180322-CS-15197</AcctSvcrRef> +<PmtInfId>13TL-180322-MS-32279</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="EUR">3</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>KOWALSKI JAN</Nm> +<PstlAdr> +<Ctry>PL</Ctry> +<AdrLine>SZCZYTNICKA 9</AdrLine> +<AdrLine>PL WROCLAW</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>Invoice 45678</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-23</Dt> +</ValDt> +<AcctSvcrRef>08922018031005244600/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">6000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>31XY-180322-MS-85571</MsgId> +<AcctSvcrRef>91AB-180322-CS-55958</AcctSvcrRef> +<PmtInfId>31XY-180322-MS-85571</PmtInfId> +<EndToEndId>NOTPROVIDED</EndToEndId> +</Refs> +<Amt Ccy="CHF">6000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Dbtr> +<Pty> +<Nm>BARBARA MUSTER</Nm> +<PstlAdr> +<AdrLine>8001 ZURICH</AdrLine> +</PstlAdr> +</Pty> +</Dbtr> +</RltdPties> +<RmtInf> +<Ustrd>RECHNUNG 67890</Ustrd> +</RmtInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>true</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>80WE-180321-CS-53986/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>RRTN</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<AmtDtls> +<TxAmt> +<Amt Ccy="CHF">3000</Amt> +</TxAmt> +</AmtDtls> +<NtryDtls> +<TxDtls> +<Refs> +<MsgId>13TJ-180321-MS-42880</MsgId> +<AcctSvcrRef>80WE-180321-CS-53986</AcctSvcrRef> +<PmtInfId>13TJ-180321-MS-42880</PmtInfId> +<EndToEndId>ETE68E82E7E701E4DB2B838318A8BA551CF</EndToEndId> +</Refs> +<Amt Ccy="CHF">3000</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RltdPties> +<Cdtr> +<Pty> +<Nm>Barbara Muster</Nm> +<PstlAdr> +<PstCd>8001</PstCd> +<TwnNm>Zuerich</TwnNm> +</PstlAdr> +</Pty> +</Cdtr> +</RltdPties> +<RtrInf> +<OrgnlBkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>ICDT</Cd> +<SubFmlyCd>DMCT</SubFmlyCd> +</Fmly> +</Domn> +</OrgnlBkTxCd> +<Orgtr> +<Id> +<OrgId> +<AnyBIC>UBSWCHZH80A</AnyBIC> +</OrgId> +</Id> +</Orgtr> +<Rsn> +<Cd>NARR</Cd> +</Rsn> +<AddtlInf>RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH</AddtlInf> +<AddtlInf>/SETT/2022-12-22T15:52:42</AddtlInf> +</RtrInf> +</TxDtls> +</NtryDtls> +</Ntry> +<Ntry> +<Amt Ccy="CHF">2.75</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>08351803222252626/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>XTND</Cd> +<Fmly> +<Cd>NTAV</Cd> +<SubFmlyCd>NTAV</SubFmlyCd> +</Fmly> +</Domn> +<Prtry> +<Cd>8037</Cd> +</Prtry> +</BkTxCd> +<AddtlNtryInf>8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.12.22</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">7761.35</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000075/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000075</MsgId> +<NbOfTxs>5</NbOfTxs> +<TtlAmt Ccy="CHF">7761.35</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 999999</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>010026540</NtryRef> +<Amt Ccy="CHF">119.45</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-21</Dt> +</ValDt> +<AcctSvcrRef>4BA02002068000015/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>IDDT</Cd> +<SubFmlyCd>PMDD</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA02002068000015</MsgId> +<NbOfTxs>1</NbOfTxs> +<TtlAmt Ccy="CHF">119.45</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +<AddtlNtryInf>?21010026540 901709</AddtlNtryInf> +</Ntry> +<Ntry> +<NtryRef>CH4531000831854071000</NtryRef> +<Amt Ccy="CHF">997.25</Amt> +<CdtDbtInd>CRDT</CdtDbtInd> +<RvslInd>false</RvslInd> +<Sts> +<Cd>BOOK</Cd> +</Sts> +<BookgDt> +<Dt>2022-12-22</Dt> +</BookgDt> +<ValDt> +<Dt>2022-12-22</Dt> +</ValDt> +<AcctSvcrRef>4BA01709118000076/1</AcctSvcrRef> +<BkTxCd> +<Domn> +<Cd>PMNT</Cd> +<Fmly> +<Cd>RCDT</Cd> +<SubFmlyCd>VCOM</SubFmlyCd> +</Fmly> +</Domn> +</BkTxCd> +<NtryDtls> +<Btch> +<MsgId>4BA01709118000076</MsgId> +<NbOfTxs>5</NbOfTxs> +<TtlAmt Ccy="CHF">997.25</TtlAmt> +<CdtDbtInd>CRDT</CdtDbtInd> +</Btch> +</NtryDtls> +</Ntry> +</Stmt> +</BkToCstmrStmt> +</Document> +\ No newline at end of file diff --git a/testbench/sample/cs/camt.053_SPS_08_088583185407_WD_0885831854071000_20221223_010729778000.xml b/testbench/sample/cs/camt.053_SPS_08_088583185407_WD_0885831854071000_20221223_010729778000.xml @@ -0,0 +1,1475 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08 ../../../../../../../camt/Testbank_Examples_Draft_V2019/XSD/camt.053.001.08.xsd" + xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08"> + <BkToCstmrStmt> + <GrpHdr> + <MsgId>CAMT053_20221223_010729756_VJC7LIIF</MsgId> + <CreDtTm>2022-12-23T01:07:29.756Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/2.0/PROD</AddtlInf> + </GrpHdr> + <Stmt> + <Id>cbe792bcaaf74a87b6c5c0c77df10872</Id> + <ElctrncSeqNb>58</ElctrncSeqNb> + <CreDtTm>2022-12-23T01:07:29.778Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-12-22T00:00:00+01:00</FrDtTm> + <ToDtTm>2022-12-22T23:59:00+01:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <Othr> + <Id>0885831854071000</Id> + </Othr> + </Id> + <Ccy>CHF</Ccy> + <Ownr> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <AdrLine>Zürich</AdrLine> + </PstlAdr> + </Ownr> + <Svcr> + <FinInstnId> + <BICFI>CRESCHZZ80A</BICFI> + <Nm>CREDIT SUISSE (Switzerland) Ltd.</Nm> + <Othr> + <Id>CHE-116.285.487 MWST</Id> + <Issr>VAT-ID</Issr> + </Othr> + </FinInstnId> + </Svcr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">7751.38</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>FWAV</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">25153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-23</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>CLAV</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">19153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>CLBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">25153.89</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2022-12-22</Dt> + </Dt> + </Bal> + <TxsSummry> + <TtlNtries> + <NbOfNtries>16</NbOfNtries> + <Sum>18138.73</Sum> + <TtlNetNtry> + <Amt>17402.51</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + </TtlNetNtry> + </TtlNtries> + <TtlCdtNtries> + <NbOfNtries>8</NbOfNtries> + <Sum>17770.62</Sum> + </TtlCdtNtries> + <TtlDbtNtries> + <NbOfNtries>8</NbOfNtries> + <Sum>368.11</Sum> + </TtlDbtNtries> + </TxsSummry> + <Ntry> + <Amt Ccy="CHF">2.36</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-43783/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="EUR">2</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="EUR">2</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">2.36</Amt> + <CcyXchg> + <SrcCcy>EUR</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>1.18</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MSG0150D4D8E71C447EBF774FB84E1F7946</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43783</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208215187</PmtInfId> + <InstrId>CLVL-1-18032711450502-1</InstrId> + <EndToEndId>ETEF9123BE97B2243629A9CF12FC6B6B80D</EndToEndId> + </Refs> + <Amt Ccy="EUR">2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Barbara Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Jan Kowalski</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>Szczytnicka 9</AdrLine> + <AdrLine>50-382 Wroclaw</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>PL79105015751000002345678901</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGBPLPW</BICFI> + <Nm>ING BANK SLASKI SA</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>UL. SOKOLSKA 34 40-086 KATOWICE </AdrLine> + <AdrLine>PL</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">4.78</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQN-180322-CS-58740/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">5</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">5</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">4.78</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>0.95611387</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">5</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> + <PmtInfId>BLVL-1-18032208093429</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="USD">5</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG40BF23DB52794241A8DBE60391E04976</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43794</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208093429</PmtInfId> + <InstrId>CLVL-1-18032711020928-1</InstrId> + <EndToEndId>ETE6A71EE9E18FF485EAC881A3B2E93475A</EndToEndId> + </Refs> + <Amt Ccy="USD">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Barbara Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period + taking into account the product-specific terms and conditions.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">9.57</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-43962/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="USD">10</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="USD">10</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">9.57</Amt> + <CcyXchg> + <SrcCcy>USD</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>0.95711254</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">23</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">5</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + <Rcrd> + <Amt Ccy="CHF">18</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>EXTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> + <PmtInfId>BLVL-1-18032208261993</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="USD">10</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSGEADAC6D735B14EEBA29FB52A459DD44F</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43705</AcctSvcrRef> + <PmtInfId>BLVL-1-18032208261993</PmtInfId> + <InstrId>CLVL-1-18032711084266-1</InstrId> + <EndToEndId>ETE1B58D1C4D44F4D75A481832C36D54D3E</EndToEndId> + </Refs> + <Amt Ccy="USD">10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>XBCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Barbara Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Jan Kowalski</Nm> + <PstlAdr> + <StrtNm>Szczytnicka 9</StrtNm> + <PstCd>50-382</PstCd> + <TwnNm>Wroclaw</TwnNm> + <Ctry>PL</Ctry> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>PL79105015751000002345678901</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <BICFI>INGBPLPW</BICFI> + <Nm>ING BANK SLASKI SA</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>UL. SOKOLSKA 34 40-086 KATOWICE </AdrLine> + <AdrLine>PL</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Invoice AB-123-C</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?62Relevant charges will be billed at the end of the accounting period + taking into account the product-specific terms and conditions.</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">10.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQN-180322-CS-58062/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">10.1</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">10.1</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>MSG0D6E675AB5794B5BA889A0CCEAAD1D16</MsgId> + <AcctSvcrRef>DNQN-180322-CS-58062</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207545645</PmtInfId> + <InstrId>5139/180314/1ABC</InstrId> + <EndToEndId>5139/180314/1ABC</EndToEndId> + </Refs> + <Amt Ccy="CHF">10.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Seefeldstrasse 1</AdrLine> + <AdrLine>8008 Zurich</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>Rechnungsnummer 18C527-005</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">10.2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-40797/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">10.2</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">10.2</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> + <PmtInfId>BLVL-1-18032207590104</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="CHF">10.2</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG71784A43AF5747B6A60C17CFD29B1712</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43716</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207590104</PmtInfId> + <InstrId>CLVL-1-18032710592518-1</InstrId> + <EndToEndId>ETE53005D7923CD49509A3E7DB9BEC094A9</EndToEndId> + </Refs> + <Amt Ccy="CHF">10.2</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Barbara Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNWL-180322-CS-87851/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>BOOK</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">100</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">100</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>57af4bcfda8d4f8fb958c5424d73c12e</MsgId> + <AcctSvcrRef>DNWL-180322-CS-87851</AcctSvcrRef> + <PmtInfId>DNCS-20220322-IXN0</PmtInfId> + <InstrId>DNCS-20220322-IXN0-TXN0</InstrId> + <EndToEndId>SP-57273905-0</EndToEndId> + </Refs> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>Barbara Muster, Zürich</Nm> + <PstlAdr> + <AdrLine>Barbara Muster, Zürich</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH3704835833740031000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>04835</MmbId> + </ClrSysMmbId> + <Nm>Credit Suisse (Schweiz) AG</Nm> + <PstlAdr> + <AdrLine>Paradeplatz 8</AdrLine> + <AdrLine>8070 Zürich CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNQR-180322-CS-40193/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">120</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">120</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> + <PmtInfId>BLVL-1-18032207463420</PmtInfId> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="CHF">120</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG270C529F8169437186D63B1339FC09F9</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43727</AcctSvcrRef> + <PmtInfId>BLVL-1-18032207463420</PmtInfId> + <InstrId>CLVL-1-18032710510965-1</InstrId> + <EndToEndId>ETEE529F052BD2B4C8B85F345FC543B4930</EndToEndId> + </Refs> + <Amt Ccy="CHF">120</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <UltmtDbtr> + <Pty> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <StrtNm>Hauptstrasse 1</StrtNm> + <PstCd>8001</PstCd> + <TwnNm>Zürich</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </UltmtDbtr> + <Cdtr> + <Pty> + <Nm>Aero Club der Schweiz</Nm> + <PstlAdr> + <AdrLine>Lidostrasse 5</AdrLine> + <AdrLine>6006 Luzern</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH0930778123456789000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00778</MmbId> + </ClrSysMmbId> + <Nm>Luzerner Kantonalbank AG</Nm> + <PstlAdr> + <AdrLine>Pilatusstrasse 12</AdrLine> + <AdrLine>6002 Luzern CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>047280000701047470007679672</Ref> + </CdtrRefInf> + <AddtlRmtInf>Aero Club der Schweiz</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">111.1</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>DNRD-180323-CS-75599/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <InstdAmt> + <Amt Ccy="CHF">111.1</Amt> + </InstdAmt> + <TxAmt> + <Amt Ccy="CHF">111.1</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <Btch> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <NbOfTxs>2</NbOfTxs> + <TtlAmt Ccy="CHF">111.1</TtlAmt> + </Btch> + <TxDtls> + <Refs> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43738</AcctSvcrRef> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <InstrId>CLVL-1-19030708451663-1</InstrId> + <EndToEndId>ETE29CDDA854EE2484ABEF9DE87A81E0C8F</EndToEndId> + </Refs> + <Amt Ccy="CHF">11.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <InitgPty> + <Pty> + <Nm>Barbara Muster</Nm> + </Pty> + </InitgPty> + <Cdtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <PstCd>8008</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH85002582584X1234560</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00258</MmbId> + </ClrSysMmbId> + <Nm>UBS Switzerland AG</Nm> + <PstlAdr> + <AdrLine>Zentralstrasse 55</AdrLine> + <AdrLine>5610 Wohlen AG 1 CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + </TxDtls> + <TxDtls> + <Refs> + <MsgId>MSG4583D8DC482546E1B19F092AC83A2665</MsgId> + <AcctSvcrRef>DNQR-180322-CS-43749</AcctSvcrRef> + <PmtInfId>BLVL-1-19030708451663</PmtInfId> + <InstrId>CLVL-1-19030708451663-2</InstrId> + <EndToEndId>ETE241D2750BC49461AAE9A98093F458940</EndToEndId> + </Refs> + <Amt Ccy="CHF">100</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <UltmtDbtr> + <Pty> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <StrtNm>Hauptstrasse 1</StrtNm> + <PstCd>8001</PstCd> + <TwnNm>Zürich</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </UltmtDbtr> + <Cdtr> + <Pty> + <Nm>Aero Club der Schweiz</Nm> + <PstlAdr> + <AdrLine>Lidostrasse 5</AdrLine> + <AdrLine>6006 Luzern</AdrLine> + </PstlAdr> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH0930778123456789000</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <CdtrAgt> + <FinInstnId> + <ClrSysMmbId> + <ClrSysId> + <Cd>CHBCC</Cd> + </ClrSysId> + <MmbId>00778</MmbId> + </ClrSysMmbId> + <Nm>Luzerner Kantonalbank AG</Nm> + <PstlAdr> + <AdrLine>Pilatusstrasse 12</AdrLine> + <AdrLine>6002 Luzern CH</AdrLine> + </PstlAdr> + </FinInstnId> + </CdtrAgt> + </RltdAgts> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>047280000701047470007679688</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">2.8</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>08351803222247667/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8037</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG + 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.03.18</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WL-180322-CS-55958/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TF-180322-MS-85571</MsgId> + <AcctSvcrRef>80WL-180322-CS-55958</AcctSvcrRef> + <PmtInfId>13TF-180322-MS-85571</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + <UETR>eb6305c9-1f7f-49de-aed0-16487c27b42f</UETR> + </Refs> + <Amt Ccy="CHF">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>BARBARA MUSTER</Nm> + <PstlAdr> + <AdrLine>8001 ZURICH</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>RECHNUNG 23456</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3.47</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WR-180322-CS-15197/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ESCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="EUR">3</Amt> + </TxAmt> + <CntrValAmt> + <Amt Ccy="CHF">3.47</Amt> + <CcyXchg> + <SrcCcy>EUR</SrcCcy> + <TrgtCcy>CHF</TrgtCcy> + <XchgRate>1.15632286</XchgRate> + <QtnDt>2022-12-22T00:00:00.000+01:00</QtnDt> + </CcyXchg> + </CntrValAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TL-180322-MS-32279</MsgId> + <AcctSvcrRef>80WR-180322-CS-15197</AcctSvcrRef> + <PmtInfId>13TL-180322-MS-32279</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + </Refs> + <Amt Ccy="EUR">3</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>KOWALSKI JAN</Nm> + <PstlAdr> + <Ctry>PL</Ctry> + <AdrLine>SZCZYTNICKA 9</AdrLine> + <AdrLine>PL WROCLAW</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>Invoice 45678</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">6000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-23</Dt> + </ValDt> + <AcctSvcrRef>08922018031005244600/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">6000</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>31XY-180322-MS-85571</MsgId> + <AcctSvcrRef>91AB-180322-CS-55958</AcctSvcrRef> + <PmtInfId>31XY-180322-MS-85571</PmtInfId> + <EndToEndId>NOTPROVIDED</EndToEndId> + </Refs> + <Amt Ccy="CHF">6000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>BARBARA MUSTER</Nm> + <PstlAdr> + <AdrLine>8001 ZURICH</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Ustrd>RECHNUNG 67890</Ustrd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>true</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80WE-180321-CS-53986/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>RRTN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">3000</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13TJ-180321-MS-42880</MsgId> + <AcctSvcrRef>80WE-180321-CS-53986</AcctSvcrRef> + <PmtInfId>13TJ-180321-MS-42880</PmtInfId> + <EndToEndId>ETE68E82E7E701E4DB2B838318A8BA551CF</EndToEndId> + </Refs> + <Amt Ccy="CHF">3000</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Cdtr> + <Pty> + <Nm>Barbara Muster</Nm> + <PstlAdr> + <PstCd>8001</PstCd> + <TwnNm>Zuerich</TwnNm> + </PstlAdr> + </Pty> + </Cdtr> + </RltdPties> + <RtrInf> + <OrgnlBkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>DMCT</SubFmlyCd> + </Fmly> + </Domn> + </OrgnlBkTxCd> + <Orgtr> + <Id> + <OrgId> + <AnyBIC>UBSWCHZH80A</AnyBIC> + </OrgId> + </Id> + </Orgtr> + <Rsn> + <Cd>NARR</Cd> + </Rsn> + <AddtlInf>RETOUR SIC VAL 22.03.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH</AddtlInf> + <AddtlInf>/SETT/2022-12-22T15:52:42</AddtlInf> + </RtrInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <Amt Ccy="CHF">2.75</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>08351803222252626/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>XTND</Cd> + <Fmly> + <Cd>NTAV</Cd> + <SubFmlyCd>NTAV</SubFmlyCd> + </Fmly> + </Domn> + <Prtry> + <Cd>8037</Cd> + </Prtry> + </BkTxCd> + <AddtlNtryInf>8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL + WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am + 22.03.18</AddtlNtryInf> + </Ntry> + <Ntry> + <NtryRef>010026540</NtryRef> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80UL-171123-CS-35153/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">7761.35</Amt> + </TxAmt> + </AmtDtls> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13RG-171123-MS-49259</MsgId> + <AcctSvcrRef>80UL-171123-CS-35153</AcctSvcrRef> + <PmtInfId>13RG-171123-MS-49259</PmtInfId> + <EndToEndId>E2EBP11-ESR12171123</EndToEndId> + </Refs> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Bundesplatz 1</AdrLine> + <AdrLine>3003 Bern</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999111122233344455678805</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>?21010026540 999999</AddtlNtryInf> + </Ntry> + <Ntry> + <NtryRef>CH4531000831854071000</NtryRef> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>80UL171123CS35154/1001</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>VCOM</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">997.25</Amt> + </TxAmt> + </AmtDtls> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>13RG-171123-MS-49260</MsgId> + <AcctSvcrRef>80UL-171123-CS-35154</AcctSvcrRef> + <PmtInfId>13RG-171123-MS-49260</PmtInfId> + <EndToEndId>E2EBP11-ESR12171124</EndToEndId> + <UETR>eb6305c9-1f7f-49de-aed0-16487c27b42d</UETR> + </Refs> + <Amt Ccy="CHF">997.25</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">0.10</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">0.10</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>INTERNAL</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Max Muster</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Bundesplatz 1</AdrLine> + <AdrLine>3003 Bern</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + <UltmtDbtr> + <Pty> + <Nm>Pia-Maria Rutschmann-Schnyder</Nm> + <PstlAdr> + <Ctry>CH</Ctry> + <AdrLine>Grosse Marktgasse 28</AdrLine> + <AdrLine>9400 Rorschach</AdrLine> + </PstlAdr> + </Pty> + </UltmtDbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>QRR</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999111122233344455678805</Ref> + </CdtrRefInf> + <AddtlRmtInf>Manuelle Bemerkung</AddtlRmtInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Stmt> + </BkToCstmrStmt> +</Document> diff --git a/testbench/sample/cs/camt.054_SIC_04_088583185407_NN_0885831854071000_20221022_170251_005.xml b/testbench/sample/cs/camt.054_SIC_04_088583185407_NN_0885831854071000_20221022_170251_005.xml @@ -0,0 +1,313 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>CAMT054_20221022_180251119_4Z2WCTQ4</MsgId> + <CreDtTm>2022-10-22T17:02:51.119Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + </GrpHdr> + <Ntfctn> + <Id>4BA01709118000075</Id> + <CreDtTm>2022-10-22T17:02:51.119Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-10-22T00:00:00.000+01:00</FrDtTm> + <ToDtTm>2022-10-22T23:59:59.999+01:00</ToDtTm> + </FrToDt> + <RptgSrc> + <Prtry>C53F</Prtry> + </RptgSrc> + <Acct> + <Id> + <IBAN>CH7705881831854071000</IBAN> + </Id> + </Acct> + <Ntry> + <NtryRef>010026540</NtryRef> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-10-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-10-22</Dt> + </ValDt> + <AcctSvcrRef>4BA01709118000075/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <Btch> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">7761.35</TtlAmt> + </Btch> + <TxDtls> + <Amt Ccy="CHF">2561.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2561.35</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Example SA</Nm> + <PstlAdr> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678028</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1400.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1400.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Bäckerei-Konditorei Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678033</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1200.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1200.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>NOTPROVIDED</Nm> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678049</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1100.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1100.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>NOTPROVIDED</Nm> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678057</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1500.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1500.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>NOTPROVIDED</Nm> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678065</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + <Ntry> + <NtryRef>010026540</NtryRef> + <Amt Ccy="CHF">119.45</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2022-10-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-10-21</Dt> + </ValDt> + <AcctSvcrRef>4BA02002068000015/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <Btch> + <NbOfTxs>1</NbOfTxs> + <TtlAmt Ccy="CHF">119.45</TtlAmt> + </Btch> + <TxDtls> + <Amt Ccy="CHF">119.45</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">119.45</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Nm>Peter Muster</Nm> + <PstlAdr> + <StrtNm>Musterstrasse 5</StrtNm> + <PstCd>8001</PstCd> + <TwnNm>Zuerich</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>901709123456789012345000003</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/cs/camt.054_SPS_08_088583185407_NN_0885831854071000_170251_005.xml b/testbench/sample/cs/camt.054_SPS_08_088583185407_NN_0885831854071000_170251_005.xml @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- camt.054 for LSV/BDD, structure subject to change, do not rely on optional tags --> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>CAMT054_20221222_180251119_4Z2WCTQ4</MsgId> + <CreDtTm>2022-12-22T17:02:51.119Z</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + </GrpHdr> + <Ntfctn> + <Id>4BA01709118000075</Id> + <CreDtTm>2022-12-22T17:02:51.119Z</CreDtTm> + <FrToDt> + <FrDtTm>2022-12-22T00:00:00.000+01:00</FrDtTm> + <ToDtTm>2022-12-22T23:59:59.999+01:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <IBAN>CH7705881831854071000</IBAN> + </Id> + </Acct> + <Ntry> + <NtryRef>010026540</NtryRef> + <Amt Ccy="CHF">7761.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2022-12-22</Dt> + </BookgDt> + <ValDt> + <Dt>2022-12-22</Dt> + </ValDt> + <AcctSvcrRef>4BA01709118000075/1</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <Btch> + <NbOfTxs>5</NbOfTxs> + <TtlAmt Ccy="CHF">7761.35</TtlAmt> + </Btch> + <TxDtls> + <Amt Ccy="CHF">2561.35</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">2561.35</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Example SA</Nm> + <PstlAdr> + <AdrLine>Place du Marché 1</AdrLine> + <AdrLine>2222 Village</AdrLine> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678028</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1400.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1400.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Bäckerei-Konditorei Meier</Nm> + <PstlAdr> + <StrtNm>Landstrasse</StrtNm> + <BldgNb>1</BldgNb> + <PstCd>5555</PstCd> + <TwnNm>Unterdorf</TwnNm> + <Ctry>CH</Ctry> + </PstlAdr> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678033</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1200.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1200.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>NOTPROVIDED</Nm> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678049</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1100.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1100.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>NOTPROVIDED</Nm> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678057</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + <TxDtls> + <Amt Ccy="CHF">1500.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <AmtDtls> + <TxAmt> + <Amt Ccy="CHF">1500.00</Amt> + </TxAmt> + </AmtDtls> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>IDDT</Cd> + <SubFmlyCd>PMDD</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>NOTPROVIDED</Nm> + </Pty> + </Dbtr> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Tp> + <CdOrPrtry> + <Prtry>ISR Reference</Prtry> + </CdOrPrtry> + </Tp> + <Ref>999999123456789012345678065</Ref> + </CdtrRefInf> + </Strd> + </RmtInf> + </TxDtls> + </NtryDtls> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347.xml b/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.052.001.04 file:///C:/Users/alihodzica/Desktop/camt.052/camt.052.001.04.xsd"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>20190424375204223062173</MsgId> + <CreDtTm>2019-04-24T16:07:09</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.6/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>20190424375204223062174</Id> + <ElctrncSeqNb>78</ElctrncSeqNb> + <CreDtTm>2019-04-24T16:07:09</CreDtTm> + <FrToDt> + <FrDtTm>2019-04-24T00:00:00</FrDtTm> + <ToDtTm>2019-04-24T16:00:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <IBAN>CH2909000000250094239</IBAN> + </Id> + <Ownr> + <Nm>Robert Schneider SA Grands magasins Biel/Bienne</Nm> + </Ownr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">208509.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">207596.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>XPCD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">207596.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Ntry> + <Amt Ccy="CHF">103.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-24</Dt> + </ValDt> + <AcctSvcrRef>074820002ZU1EPZK</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>20190423-000369773</MsgId> + <AcctSvcrRef>25-1120172999-1</AcctSvcrRef> + <PmtInfId>30003101</PmtInfId> + <EndToEndId>20190423001255000100005</EndToEndId> + </Refs> + <Amt Ccy="CHF">103.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">913.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-24</Dt> + </ValDt> + <AcctSvcrRef>074820002ZU1EQ0K</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>20190423-000369773</MsgId> + <AcctSvcrRef>25-1120172999-2</AcctSvcrRef> + <PmtInfId>30003101</PmtInfId> + <EndToEndId>20190423001255000100006</EndToEndId> + </Refs> + <Amt Ccy="CHF">913.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101</AddtlNtryInf> + </Ntry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347_v2019.xml b/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347_v2019.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08 file:///C:/Users/burkhalterl/Documents/Musterfiles%20ISOV19/Schemen/camt.052.001.08.xsd"> + <BkToCstmrAcctRpt> + <GrpHdr> + <MsgId>20190424375204223062173</MsgId> + <CreDtTm>2019-04-24T16:07:09</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/2.0/PROD</AddtlInf> + </GrpHdr> + <Rpt> + <Id>20190424375204223062174</Id> + <ElctrncSeqNb>78</ElctrncSeqNb> + <CreDtTm>2019-04-24T16:07:09</CreDtTm> + <FrToDt> + <FrDtTm>2019-04-24T00:00:00</FrDtTm> + <ToDtTm>2019-04-24T16:00:00</ToDtTm> + </FrToDt> + <Acct> + <Id> + <IBAN>CH2909000000250094239</IBAN> + </Id> + <Ccy>CHF</Ccy> + <Ownr> + <Nm>Robert Schneider SA Grands magasins Biel/Bienne</Nm> + </Ownr> + </Acct> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>OPBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">208509.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>ITBD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">207596.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Bal> + <Tp> + <CdOrPrtry> + <Cd>XPCD</Cd> + </CdOrPrtry> + </Tp> + <Amt Ccy="CHF">207596.19</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <Dt> + <Dt>2019-04-24</Dt> + </Dt> + </Bal> + <Ntry> + <Amt Ccy="CHF">103.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-24</Dt> + </ValDt> + <AcctSvcrRef>074820002ZU1EPZK</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>20190423-000369773</MsgId> + <AcctSvcrRef>25-1120172999-1</AcctSvcrRef> + <PmtInfId>30003101</PmtInfId> + <EndToEndId>20190423001255000100005</EndToEndId> + <UETR>b009c997-97b3-4a9c-803c-d645a7276bf2</UETR> + </Refs> + <Amt Ccy="CHF">103.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101</AddtlNtryInf> + </Ntry> + <Ntry> + <Amt Ccy="CHF">913.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-24</Dt> + </ValDt> + <AcctSvcrRef>074820002ZU1EQ0K</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>ICDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <TxDtls> + <Refs> + <MsgId>20190423-000369773</MsgId> + <AcctSvcrRef>25-1120172999-2</AcctSvcrRef> + <PmtInfId>30003101</PmtInfId> + <EndToEndId>20190423001255000100006</EndToEndId> + <UETR>b009c997-97b3-4a9c-803c-d645a7276bf1</UETR> + </Refs> + <Amt Ccy="CHF">913.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101</AddtlNtryInf> + </Ntry> + </Rpt> + </BkToCstmrAcctRpt> +</Document> diff --git a/testbench/sample/200519_camt054-Credit_P_CH2909000000250094239_1110092691_0_2019042421291293.xml b/testbench/sample/postfinance/200519_camt054-Credit_P_CH2909000000250094239_1110092691_0_2019042421291293.xml diff --git a/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2009.xml b/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2009.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04 file:///C:/Users/alihodzica/Desktop/camt.054/camt.054.001.04.xsd"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>20190424375204228750928</MsgId> + <CreDtTm>2019-04-25T00:20:05</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/1.6/PROD</AddtlInf> + </GrpHdr> + <Ntfctn> + <Id>20190424375204228750931</Id> + <CreDtTm>2019-04-25T00:20:05</CreDtTm> + <FrToDt> + <FrDtTm>2019-04-24T00:00:00</FrDtTm> + <ToDtTm>2019-04-24T23:59:59</ToDtTm> + </FrToDt> + <RptgSrc> + <Prtry>OTHR</Prtry> + </RptgSrc> + <Acct> + <Id> + <IBAN>CH2909000000250094239</IBAN> + </Id> + <Ownr> + <Nm>Robert Schneider SA</Nm> + </Ownr> + </Acct> + <Ntry> + <NtryRef>020010001</NtryRef> + <Amt Ccy="CHF">147.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts>BOOK</Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-25</Dt> + </ValDt> + <AcctSvcrRef>100820002V496ZRA</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>CNTR</Cd> + <SubFmlyCd>CWDL</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">4.40</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>6</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <NbOfTxs>1</NbOfTxs> + </Btch> + <TxDtls> + <Refs> + <AcctSvcrRef>180410CH02UZ2PC1</AcctSvcrRef> + <Prtry> + <Tp>06</Tp> + <Ref>20190423848301000100105</Ref> + </Prtry> + </Refs> + <Amt Ccy="CHF">147.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>CNTR</Cd> + <SubFmlyCd>CWDL</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">4.40</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>6</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Cdtr> + <Nm>Maria Bernasconi</Nm> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5109000000250092291</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Ref>100041698214115449371805278</Ref> + </CdtrRefInf> + <AddtlRmtInf>?REJECT?0</AddtlRmtInf> + </Strd> + </RmtInf> + <RltdDts> + <AccptncDtTm>2019-04-23T20:00:00</AccptncDtTm> + </RltdDts> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>SAMMELLASTSCHRIFT ASR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 02-1000-1 PAKET ID: 180410CH00000AL0</AddtlNtryInf> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2019.xml b/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2019.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08 file:///C:/Users/zwahlenma/Desktop/camt.054.001.08.xsd"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>20190424375204228750928</MsgId> + <CreDtTm>2019-04-25T00:20:05</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>SPS/2.0/PROD</AddtlInf> + </GrpHdr> + <Ntfctn> + <Id>20190424375204228750931</Id> + <CreDtTm>2019-04-25T00:20:05</CreDtTm> + <FrToDt> + <FrDtTm>2019-04-24T00:00:00</FrDtTm> + <ToDtTm>2019-04-24T23:59:59</ToDtTm> + </FrToDt> + <Acct> + <Id> + <IBAN>CH2909000000250094239</IBAN> + </Id> + <Ccy>CHF</Ccy> + <Ownr> + <Nm>Robert Schneider SA</Nm> + </Ownr> + </Acct> + <Ntry> + <NtryRef>020010001</NtryRef> + <Amt Ccy="CHF">147.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2019-04-24</Dt> + </BookgDt> + <ValDt> + <Dt>2019-04-25</Dt> + </ValDt> + <AcctSvcrRef>100820002V496ZRA</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>CNTR</Cd> + <SubFmlyCd>CWDL</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">4.40</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>6</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <NtryDtls> + <Btch> + <NbOfTxs>1</NbOfTxs> + </Btch> + <TxDtls> + <Refs> + <AcctSvcrRef>180410CH02UZ2PC1</AcctSvcrRef> + <Prtry> + <Tp>06</Tp> + <Ref>20190423848301000100105</Ref> + </Prtry> + </Refs> + <Amt Ccy="CHF">147.00</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>CNTR</Cd> + <SubFmlyCd>CWDL</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <Chrgs> + <TtlChrgsAndTaxAmt Ccy="CHF">4.40</TtlChrgsAndTaxAmt> + <Rcrd> + <Amt Ccy="CHF">4.40</Amt> + <CdtDbtInd>DBIT</CdtDbtInd> + <ChrgInclInd>false</ChrgInclInd> + <Tp> + <Prtry> + <Id>6</Id> + </Prtry> + </Tp> + </Rcrd> + </Chrgs> + <RltdPties> + <Cdtr> + <Pty> + <Nm>Maria Bernasconi</Nm> + </Pty> + </Cdtr> + <CdtrAcct> + <Id> + <IBAN>CH5109000000250092291</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RmtInf> + <Strd> + <CdtrRefInf> + <Ref>100041698214115449371805278</Ref> + </CdtrRefInf> + <AddtlRmtInf>?REJECT?0</AddtlRmtInf> + </Strd> + </RmtInf> + <RltdDts> + <AccptncDtTm>2019-04-23T20:00:00</AccptncDtTm> + </RltdDts> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>SAMMELLASTSCHRIFT ASR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 02-1000-1 PAKET ID: 180410CH00000AL0</AddtlNtryInf> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/testbench/sample/200519_camt054-chdd_p_ch2909000000250094239_1110097484_0_20190520700381159_v2019.xml b/testbench/sample/postfinance/200519_camt054-chdd_p_ch2909000000250094239_1110097484_0_20190520700381159_v2019.xml diff --git a/testbench/sample/camt053_P_CH2909000000250094239_1110092698_0_2020062503071366_v2009.xml b/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_2020062503071366_v2009.xml diff --git a/testbench/sample/camt053_P_CH2909000000250094239_1110092698_0_2020112503071366_v2019.xml b/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_2020112503071366_v2019.xml diff --git a/testbench/sample/camt054-CHDD_P_CH2909000000250094239_1110097484_0_20220615375204228751067.xml b/testbench/sample/postfinance/camt054-CHDD_P_CH2909000000250094239_1110097484_0_20220615375204228751067.xml diff --git a/testbench/sample/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2009.xml b/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2009.xml diff --git a/testbench/sample/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2019.xml b/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2019.xml diff --git a/testbench/sample/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2009.xml b/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2009.xml diff --git a/testbench/sample/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2019.xml b/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2019.xml diff --git a/testbench/sample/pain002_CHDD_P_CH2909000000250094239_1110097483_0_20220614375204216308259.xml b/testbench/sample/postfinance/pain002_CHDD_P_CH2909000000250094239_1110097483_0_20220614375204216308259.xml diff --git a/testbench/src/main/kotlin/Main.kt b/testbench/src/main/kotlin/Main.kt @@ -20,7 +20,9 @@ package tech.libeufin.testbench import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult +import com.github.ajalt.clikt.core.main import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.testing.test import io.ktor.client.* @@ -28,9 +30,10 @@ import io.ktor.client.engine.cio.* import io.ktor.http.* import kotlinx.coroutines.runBlocking import kotlinx.serialization.Serializable -import tech.libeufin.common.ANSI +import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.* +import java.time.Instant import kotlin.io.path.* val nexusCmd = LibeufinNexus() @@ -70,7 +73,9 @@ data class Config( val payto: Map<String, String> ) -class Cli : CliktCommand("Run integration tests on banks provider") { +class Cli : CliktCommand() { + override fun help(context: Context) = "Run integration tests on banks provider" + val platform by argument() override fun run() { @@ -90,10 +95,10 @@ class Cli : CliktCommand("Run integration tests on banks provider") { LIBEUFIN_NEXUS_HOME = test/$platform [nexus-fetch] - FREQUENCY = 5d + FREQUENCY = 4h [nexus-submit] - FREQUENCY = 5d + FREQUENCY = 4h [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufintestbench @@ -127,7 +132,7 @@ class Cli : CliktCommand("Run integration tests on banks provider") { val dummyPaytos = mapOf( "CHF" to "payto://iban/CH4189144589712575493?receiver-name=John%20Smith", - "EUR" to "payto://iban/DE54500105177452372744?receiver-name=John%20Smith" + "EUR" to "payto://iban/DE18500105173385245162?receiver-name=John%20Smith" ) val dummyPayto = requireNotNull(dummyPaytos[currency]) { "Missing dummy payto for $currency" @@ -137,7 +142,7 @@ class Cli : CliktCommand("Run integration tests on banks provider") { val recoverDoc = "report statement notification" runBlocking { step("Init ${kind.name}") - + assert(nexusCmd.run("dbinit $flags")) val cmds = buildMap { @@ -176,41 +181,39 @@ class Cli : CliktCommand("Run integration tests on banks provider") { bankKeysPath.deleteIfExists() Unit }) - if (kind.test) { - put("tx", suspend { - step("Submit one transaction") - nexusCmd.run("initiate-payment $flags \"$payto&amount=$currency:42&message=single%20transaction%20test\"") - nexusCmd.run("ebics-submit $ebicsFlags") - Unit - }) - put("txs", suspend { - step("Submit many transaction") - repeat(4) { - nexusCmd.run("initiate-payment $flags --amount=$currency:${100L+it} --subject \"multi transaction test $it\" \"$payto\"") - } - nexusCmd.run("ebics-submit $ebicsFlags") - Unit - }) - } else { - put("tx", suspend { - step("Submit new transaction") - nexusCmd.run("initiate-payment $flags \"$payto&amount=$currency:1.1&message=single%20transaction%20test\"") - nexusCmd.run("ebics-submit $ebicsFlags") - Unit - }) - } + put("tx", suspend { + step("Initiate a new transaction") + val now = Instant.now() + nexusCmd.run("initiate-payment $flags --amount=$currency:0.1 --subject \"single $now\" \"$payto\"") + Unit + }) + put("txs", suspend { + step("Initiate four new transactions") + val now = Instant.now() + repeat(4) { + nexusCmd.run("initiate-payment $flags --amount=$currency:${(10.0+it)/100} --subject \"multi $it $now\" \"$payto\"") + } + }) put("tx-bad-name", suspend { val badPayto = URLBuilder().takeFrom(payto) badPayto.parameters["receiver-name"] = "John Smith" - step("Submit new transaction with a bad name") - nexusCmd.run("initiate-payment $flags \"$badPayto&amount=$currency:1.1&message=This%20should%20fail%20because%20bad%20name\"") - nexusCmd.run("ebics-submit $ebicsFlags") + step("Initiate a new transaction with a bad name") + val now = Instant.now() + nexusCmd.run("initiate-payment $flags --amount=$currency:0.21 --subject \"bad name $now\" \"$badPayto\"") + Unit + }) + put("tx-bad-iban", suspend { + val badPayto = URLBuilder().takeFrom("payto://iban/XX18500105173385245165") + badPayto.parameters["receiver-name"] = "John Smith" + step("Initiate a new transaction to a bad IBAN") + val now = Instant.now() + nexusCmd.run("initiate-payment $flags --amount=$currency:0.22 --subject \"bad iban $now\" \"$badPayto\"") Unit }) - put("tx-dummy", suspend { - step("Submit new transaction to a dummy IBAN") - nexusCmd.run("initiate-payment $flags \"$dummyPayto&amount=$currency:1.1&message=This%20should%20fail%20because%20dummy\"") - nexusCmd.run("ebics-submit $ebicsFlags") + put("tx-dummy-iban", suspend { + step("Initiate a new transaction to a dummy IBAN") + val now = Instant.now() + nexusCmd.run("initiate-payment $flags --amount=$currency:0.23 --subject \"dummy iban $now\" \"$dummyPayto\"") Unit }) put("tx-check", "Check transaction semantic", "testing tx-check $flags") diff --git a/testbench/src/test/kotlin/IntegrationTest.kt b/testbench/src/test/kotlin/IntegrationTest.kt @@ -37,7 +37,8 @@ import tech.libeufin.common.api.engine import tech.libeufin.common.db.one import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.LibeufinNexus -import tech.libeufin.nexus.cli.ingestIncomingPayment +import tech.libeufin.nexus.cli.registerIncomingPayment +import tech.libeufin.nexus.iso20022.* import tech.libeufin.nexus.nexusConfig import tech.libeufin.nexus.withDb import java.time.Instant @@ -151,7 +152,6 @@ class IntegrationTest { setup("conf/integration.conf") { db -> val cfg = NexusIngestConfig.default(AccountType.exchange) val userPayTo = IbanPayto.rand() - val fiatPayTo = IbanPayto.rand() // Load conversion setup manually as the server would refuse to start without an exchange account val sqlProcedures = Path("../database-versioning/libeufin-conversion-setup.sql") @@ -163,22 +163,22 @@ class IntegrationTest { val reservePub = EddsaPublicKey.rand() val reservePayment = IncomingPayment( amount = TalerAmount("EUR:10"), - debitPaytoUri = userPayTo.toString(), - wireTransferSubject = "Error test $reservePub", + debtorPayto = userPayTo, + subject = "Error test $reservePub", executionTime = Instant.now(), bankId = "reserve_error" ) assertException("ERROR: cashin failed: missing exchange account") { - ingestIncomingPayment(db, cfg, reservePayment) + registerIncomingPayment(db, cfg, reservePayment) } // But KYC works - ingestIncomingPayment( + registerIncomingPayment( db, cfg, reservePayment.copy( bankId = "kyc", - wireTransferSubject = "Error test KYC:${EddsaPublicKey.rand()}" + subject = "Error test KYC:${EddsaPublicKey.rand()}" ) ) @@ -186,7 +186,7 @@ class IntegrationTest { bankCmd.run("create-account $flags -u exchange -p password --name 'Mr Money' --exchange") assertException("ERROR: cashin currency conversion failed: missing conversion rates") { - ingestIncomingPayment(db, cfg, reservePayment) + registerIncomingPayment(db, cfg, reservePayment) } // Start server @@ -220,7 +220,7 @@ class IntegrationTest { // Too small amount db.checkCount(1, 0, 1) - ingestIncomingPayment(db, cfg, reservePayment.copy( + registerIncomingPayment(db, cfg, reservePayment.copy( amount = TalerAmount("EUR:0.01"), )) db.checkCount(2, 1, 1) @@ -230,19 +230,19 @@ class IntegrationTest { // Check success val validPayment = reservePayment.copy( - wireTransferSubject = "Success $reservePub", + subject = "Success $reservePub", bankId = "success" ) - ingestIncomingPayment(db, cfg, validPayment) + registerIncomingPayment(db, cfg, validPayment) db.checkCount(3, 1, 2) client.get("http://0.0.0.0:8080/accounts/exchange/transactions") { basicAuth("exchange", "password") }.assertOkJson<BankAccountTransactionsResponse>() // Check idempotency - ingestIncomingPayment(db, cfg, validPayment) - ingestIncomingPayment(db, cfg, validPayment.copy( - wireTransferSubject="Success 2 $reservePub" + registerIncomingPayment(db, cfg, validPayment) + registerIncomingPayment(db, cfg, validPayment.copy( + subject="Success 2 $reservePub" )) db.checkCount(3, 1, 2) } diff --git a/testbench/src/test/kotlin/Iso20022Test.kt b/testbench/src/test/kotlin/Iso20022Test.kt @@ -18,8 +18,9 @@ */ import org.junit.Test -import tech.libeufin.nexus.ebics.* import tech.libeufin.nexus.* +import tech.libeufin.nexus.ebics.* +import tech.libeufin.nexus.iso20022.* import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.Path @@ -31,15 +32,31 @@ class Iso20022Test { @Test fun sample() { for (sample in Path("sample").listDirectoryEntries()) { - val content = Files.newInputStream(sample) - val name = sample.toString() - println(name) - if (name.contains("HAC")) { - parseCustomerAck(content) - } else if (name.contains("pain.002") || name.contains("pain002") ) { - parseCustomerPaymentStatusReport(content) + if (sample.isDirectory()) { + for (case in sample.listDirectoryEntries()) { + val content = Files.newInputStream(case) + val name = case.toString() + println(name) + if (name.contains("HAC")) { + parseCustomerAck(content) + } else if (name.contains("pain.002") || name.contains("pain002") ) { + parseCustomerPaymentStatusReport(content) + } else { + parseTx(content, "CHF", Dialect.postfinance) + } + } + } else { - parseTx(content, "CHF", Dialect.postfinance) + val content = Files.newInputStream(sample) + val name = sample.toString() + println(name) + if (name.contains("HAC")) { + parseCustomerAck(content) + } else if (name.contains("pain.002") || name.contains("pain002") ) { + parseCustomerPaymentStatusReport(content) + } else { + parseTx(content, "CHF", Dialect.postfinance) + } } } } @@ -96,6 +113,8 @@ class Iso20022Test { // Skip } else if (name.contains("HAC")) { parseCustomerAck(content) + } else if (name.contains("HAA")) { + EbicsAdministrative.parseHAA(content) } else if (name.contains("HKD")) { EbicsAdministrative.parseHKD(content) } else if (name.contains("pain.002")) { diff --git a/testbench/src/test/kotlin/MigrationTest.kt b/testbench/src/test/kotlin/MigrationTest.kt @@ -71,6 +71,9 @@ class MigrationTest { // libeufin-bank-0007 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0007.sql").readText()) + // libeufin-bank-0008 + conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0008.sql").readText()) + // libeufin-nexus-0001 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0001.sql").readText()) conn.execSQLUpdate(""" @@ -94,5 +97,14 @@ class MigrationTest { // libeufin-nexus-0006 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0006.sql").readText()) + + conn.execSQLUpdate(""" + INSERT INTO initiated_outgoing_transactions(amount, wire_transfer_subject, initiation_time, credit_payto_uri, outgoing_transaction_id, request_uid, order_id) VALUES + ((42, 0)::taler_amount, 'subject', 0, 'credit_payto', NULL, 'TX0', 'ORDER0'), + ((41, 0)::taler_amount, 'subject', 0, 'credit_payto', NULL, 'TX1', NULL); + """) + + // libeufin-nexus-0007 + conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0007.sql").readText()) } } \ No newline at end of file