diff --git a/Cargo.lock b/Cargo.lock index f29c24910..17c822bdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,7 +254,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.87", + "syn 2.0.90", "thiserror", ] @@ -301,7 +301,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -312,7 +312,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -349,6 +349,7 @@ dependencies = [ "anyhow", "async-trait", "audit", + "es-entity", "sqlx", "sqlx-adapter", "strum", @@ -363,6 +364,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "autotools" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf" +dependencies = [ + "cc", +] + [[package]] name = "axum" version = "0.7.9" @@ -452,7 +462,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -571,7 +581,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -617,6 +627,24 @@ dependencies = [ "serde", ] +[[package]] +name = "cached" +version = "0.51.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0feb64151eed3da6107fddd2d717a6ca4b9dbd74e43784c55c841d1abfe5a295" +dependencies = [ + "ahash 0.8.11", + "async-trait", + "cached_proc_macro 0.21.0", + "cached_proc_macro_types", + "futures", + "hashbrown 0.14.5", + "instant", + "once_cell", + "thiserror", + "tokio", +] + [[package]] name = "cached" version = "0.53.1" @@ -625,7 +653,7 @@ checksum = "b4d73155ae6b28cf5de4cfc29aeb02b8a1c6dab883cb015d15cd514e42766846" dependencies = [ "ahash 0.8.11", "async-trait", - "cached_proc_macro", + "cached_proc_macro 0.23.0", "cached_proc_macro_types", "futures", "hashbrown 0.14.5", @@ -635,6 +663,18 @@ dependencies = [ "web-time", ] +[[package]] +name = "cached_proc_macro" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771aa57f3b17da6c8bcacb187bb9ec9bc81c8160e72342e67c329e0e1651a669" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "cached_proc_macro" version = "0.23.0" @@ -644,7 +684,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -659,7 +699,22 @@ version = "0.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a82cb4666abbe0fadc8511e5a60b904d37ca9dacc7b65d1c06e962dbc8ed1374" dependencies = [ - "cala-cel-parser", + "cala-cel-parser 0.2.44", + "chrono", + "lazy_static", + "rust_decimal", + "serde", + "serde_json", + "thiserror", + "uuid", +] + +[[package]] +name = "cala-cel-interpreter" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" +dependencies = [ + "cala-cel-parser 0.3.3-dev", "chrono", "lazy_static", "rust_decimal", @@ -679,13 +734,71 @@ dependencies = [ "lalrpop-util", ] +[[package]] +name = "cala-cel-parser" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" +dependencies = [ + "lalrpop", + "lalrpop-util", +] + +[[package]] +name = "cala-ledger" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" +dependencies = [ + "cached 0.51.4", + "cala-cel-interpreter 0.3.3-dev", + "cala-ledger-core-types 0.3.3-dev", + "cala-tracing", + "chrono", + "derive_builder", + "es-entity", + "futures", + "opentelemetry", + "prost", + "prost-wkt-types", + "protobuf-src", + "rust_decimal", + "serde", + "serde_json", + "sqlx", + "thiserror", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", + "tonic-health", + "tracing", + "tracing-opentelemetry", + "uuid", +] + [[package]] name = "cala-ledger-core-types" version = "0.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e246bce7bf428886c00eabce22428513bb7794e6143819bbcf34522459518536" dependencies = [ - "cala-cel-interpreter", + "cala-cel-interpreter 0.2.44", + "chrono", + "derive_builder", + "rust_decimal", + "rusty-money", + "serde", + "serde_json", + "sqlx", + "thiserror", + "uuid", +] + +[[package]] +name = "cala-ledger-core-types" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" +dependencies = [ + "cala-cel-interpreter 0.3.3-dev", "chrono", "derive_builder", "rust_decimal", @@ -697,6 +810,25 @@ dependencies = [ "uuid", ] +[[package]] +name = "cala-tracing" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" +dependencies = [ + "anyhow", + "axum-extra", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "serde", + "serde_json", + "tonic", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", +] + [[package]] name = "casbin" version = "2.5.0" @@ -785,7 +917,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1012,7 +1144,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1023,7 +1155,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1058,6 +1190,30 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "deposit" +version = "0.1.0" +dependencies = [ + "anyhow", + "audit", + "authz", + "cala-ledger", + "chrono", + "core-money", + "derive_builder", + "es-entity", + "governance", + "outbox", + "rust_decimal", + "rust_decimal_macros", + "serde", + "sqlx", + "strum", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "der" version = "0.7.9" @@ -1097,7 +1253,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1107,7 +1263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1151,7 +1307,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1205,6 +1361,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "errno" version = "0.3.9" @@ -1217,9 +1383,8 @@ dependencies = [ [[package]] name = "es-entity" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9a48b924f08bdeba3e50bc6a14ca7ff8ca94abb42f6b35157a420c71551452" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" dependencies = [ "async-graphql", "async-trait", @@ -1237,9 +1402,8 @@ dependencies = [ [[package]] name = "es-entity-macros" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f06294b7c85dc3c31d390460fe17f8aa97723400186dff68fe43782e6df0f5c9" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" dependencies = [ "convert_case", "darling", @@ -1247,7 +1411,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1409,7 +1573,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2086,7 +2250,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2147,6 +2311,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" + [[package]] name = "ipnet" version = "2.10.1" @@ -2299,8 +2469,9 @@ dependencies = [ "axum", "axum-extra", "base64 0.22.1", - "cached", - "cala-ledger-core-types", + "cached 0.53.1", + "cala-ledger", + "cala-ledger-core-types 0.2.44", "chrono", "clap", "cloud-storage", @@ -2947,7 +3118,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3033,7 +3204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3071,7 +3242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.13.0", "log", "multimap", @@ -3083,7 +3254,7 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn 2.0.87", + "syn 2.0.90", "tempfile", ] @@ -3097,7 +3268,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3109,6 +3280,62 @@ dependencies = [ "prost", ] +[[package]] +name = "prost-wkt" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d84e2bee181b04c2bac339f2bfe818c46a99750488cc6728ce4181d5aa8299" +dependencies = [ + "chrono", + "inventory", + "prost", + "serde", + "serde_derive", + "serde_json", + "typetag", +] + +[[package]] +name = "prost-wkt-build" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a669d5acbe719010c6f62a64e6d7d88fdedc1fe46e419747949ecb6312e9b14" +dependencies = [ + "heck 0.4.1", + "prost", + "prost-build", + "prost-types", + "quote", +] + +[[package]] +name = "prost-wkt-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ef068e9b82e654614b22e6b13699bd545b6c0e2e721736008b00b38aeb4f64" +dependencies = [ + "chrono", + "prost", + "prost-build", + "prost-types", + "prost-wkt", + "prost-wkt-build", + "protobuf-src", + "regex", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "protobuf-src" +version = "1.1.0+21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +dependencies = [ + "autotools", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -3448,7 +3675,7 @@ checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3783,7 +4010,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3847,7 +4074,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3886,7 +4113,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3938,9 +4165,8 @@ dependencies = [ [[package]] name = "sim-time" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb970973aa489a7bc2d6b81da17eef2e45a8d5abf2d185284782ee1bbbfd6bdf" +version = "0.3.3-dev" +source = "git+https://github.com/galoymoney/cala.git?branch=main#fe03fbcc0e4243a7f094f54add7f21cc43aa7473" dependencies = [ "chrono", "serde", @@ -4138,7 +4364,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4161,7 +4387,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.87", + "syn 2.0.90", "tempfile", "tokio", "url", @@ -4345,7 +4571,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4367,9 +4593,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -4399,7 +4625,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4479,7 +4705,7 @@ checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4561,9 +4787,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -4584,7 +4810,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4707,7 +4933,20 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.87", + "syn 2.0.90", +] + +[[package]] +name = "tonic-health" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eaf34ddb812120f5c601162d5429933c9b527d901ab0e7f930d3147e33a09b2" +dependencies = [ + "async-stream", + "prost", + "tokio", + "tokio-stream", + "tonic", ] [[package]] @@ -4776,9 +5015,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -4788,20 +5027,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -4850,9 +5089,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -4860,9 +5099,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -4922,12 +5161,42 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "typetag" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba3b6e86ffe0054b2c44f2d86407388b933b16cb0a70eea3929420db1d9bbe" +dependencies = [ + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", +] + +[[package]] +name = "typetag-impl" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "ucd-trie" version = "0.1.7" @@ -5134,7 +5403,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -5168,7 +5437,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5515,7 +5784,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -5563,7 +5832,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5583,7 +5852,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -5612,5 +5881,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] diff --git a/Cargo.toml b/Cargo.toml index d0dc14de1..6e4ec4722 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "core/user", "core/governance", "core/money", + "core/deposit", "lib/authz", "lib/audit", @@ -22,8 +23,12 @@ members = [ ] [workspace.dependencies] -es-entity = "0.3.1" -sim-time = "0.3.1" +es-entity = { git = "https://github.com/galoymoney/cala.git", branch = "main" } +sim-time = { git = "https://github.com/galoymoney/cala.git", branch = "main" } +cala-ledger = { git = "https://github.com/galoymoney/cala.git", branch = "main" } +# es-entity = "0.3.1" +# sim-time = "0.3.1" +# cala-ledger = "0.3.1" anyhow = "1.0.92" async-graphql = { version = "7.0.11", default-features = false, features = ["dataloader", "tracing", "chrono", "playground"] } diff --git a/Makefile b/Makefile index 48cde8928..36865b461 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ sqlx-prepare: cd lib/outbox && cargo sqlx prepare cd core/governance && cargo sqlx prepare cd core/user && cargo sqlx prepare + cd core/deposit && cargo sqlx prepare cd lana/app && cargo sqlx prepare cd lana/dashboard && cargo sqlx prepare diff --git a/core/deposit/.sqlx/query-02617f65a7603c309ee825ba9be372c2ef44f685337992ee50bef039f3be423d.json b/core/deposit/.sqlx/query-02617f65a7603c309ee825ba9be372c2ef44f685337992ee50bef039f3be423d.json new file mode 100644 index 000000000..88bca3d2b --- /dev/null +++ b/core/deposit/.sqlx/query-02617f65a7603c309ee825ba9be372c2ef44f685337992ee50bef039f3be423d.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, id FROM core_deposits WHERE ((deposit_account_id = $1) AND (COALESCE(id < $3, true))) ORDER BY id DESC LIMIT $2) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "02617f65a7603c309ee825ba9be372c2ef44f685337992ee50bef039f3be423d" +} diff --git a/core/deposit/.sqlx/query-0911a137c1a3afe9f301cf1b019a53ff041653d94f89a52ee250c93878ea2cca.json b/core/deposit/.sqlx/query-0911a137c1a3afe9f301cf1b019a53ff041653d94f89a52ee250c93878ea2cca.json new file mode 100644 index 000000000..37511009c --- /dev/null +++ b/core/deposit/.sqlx/query-0911a137c1a3afe9f301cf1b019a53ff041653d94f89a52ee250c93878ea2cca.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM deposit_accounts WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "0911a137c1a3afe9f301cf1b019a53ff041653d94f89a52ee250c93878ea2cca" +} diff --git a/core/deposit/.sqlx/query-0a8086357bfd95aee2480af351f90dbc6c00ab45e92297732f4f548426327f4b.json b/core/deposit/.sqlx/query-0a8086357bfd95aee2480af351f90dbc6c00ab45e92297732f4f548426327f4b.json new file mode 100644 index 000000000..887a23764 --- /dev/null +++ b/core/deposit/.sqlx/query-0a8086357bfd95aee2480af351f90dbc6c00ab45e92297732f4f548426327f4b.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM deposit_accounts WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "0a8086357bfd95aee2480af351f90dbc6c00ab45e92297732f4f548426327f4b" +} diff --git a/core/deposit/.sqlx/query-0e0b27fef175ac24eb757a0e45e7b99d81e2947c6f7e64040446e0456976a483.json b/core/deposit/.sqlx/query-0e0b27fef175ac24eb757a0e45e7b99d81e2947c6f7e64040446e0456976a483.json new file mode 100644 index 000000000..97e0681d4 --- /dev/null +++ b/core/deposit/.sqlx/query-0e0b27fef175ac24eb757a0e45e7b99d81e2947c6f7e64040446e0456976a483.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM core_deposits WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "0e0b27fef175ac24eb757a0e45e7b99d81e2947c6f7e64040446e0456976a483" +} diff --git a/core/deposit/.sqlx/query-12c19a58f42d5ec96fd75e628a04d5354b6cdb3f1a7881c2fad4c424eebadefc.json b/core/deposit/.sqlx/query-12c19a58f42d5ec96fd75e628a04d5354b6cdb3f1a7881c2fad4c424eebadefc.json new file mode 100644 index 000000000..084162b24 --- /dev/null +++ b/core/deposit/.sqlx/query-12c19a58f42d5ec96fd75e628a04d5354b6cdb3f1a7881c2fad4c424eebadefc.json @@ -0,0 +1,53 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id AS \"id: AuditEntryId\", subject, object, action, authorized, recorded_at\n FROM audit_entries\n WHERE COALESCE(id < $1, true)\n ORDER BY id DESC\n LIMIT $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: AuditEntryId", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "subject", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "object", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "action", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "authorized", + "type_info": "Bool" + }, + { + "ordinal": 5, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false + ] + }, + "hash": "12c19a58f42d5ec96fd75e628a04d5354b6cdb3f1a7881c2fad4c424eebadefc" +} diff --git a/core/deposit/.sqlx/query-166f74e9bac033fe87a5db5b44357a637f216963cff3633a9523f44a46df000b.json b/core/deposit/.sqlx/query-166f74e9bac033fe87a5db5b44357a637f216963cff3633a9523f44a46df000b.json new file mode 100644 index 000000000..545c94836 --- /dev/null +++ b/core/deposit/.sqlx/query-166f74e9bac033fe87a5db5b44357a637f216963cff3633a9523f44a46df000b.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM policies WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "166f74e9bac033fe87a5db5b44357a637f216963cff3633a9523f44a46df000b" +} diff --git a/core/deposit/.sqlx/query-17f820d557424ee764e3139317d62dc19644b7d38c0d5f968af2160f741fe3dc.json b/core/deposit/.sqlx/query-17f820d557424ee764e3139317d62dc19644b7d38c0d5f968af2160f741fe3dc.json new file mode 100644 index 000000000..6c6bfa6d5 --- /dev/null +++ b/core/deposit/.sqlx/query-17f820d557424ee764e3139317d62dc19644b7d38c0d5f968af2160f741fe3dc.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM approval_processes i JOIN approval_process_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "17f820d557424ee764e3139317d62dc19644b7d38c0d5f968af2160f741fe3dc" +} diff --git a/core/deposit/.sqlx/query-1885cb45c95e595339e8dc305fc3e72bd63e66f331eab8c57980e6d7e0e64cc2.json b/core/deposit/.sqlx/query-1885cb45c95e595339e8dc305fc3e72bd63e66f331eab8c57980e6d7e0e64cc2.json new file mode 100644 index 000000000..61bd68174 --- /dev/null +++ b/core/deposit/.sqlx/query-1885cb45c95e595339e8dc305fc3e72bd63e66f331eab8c57980e6d7e0e64cc2.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM deposit_accounts WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "1885cb45c95e595339e8dc305fc3e72bd63e66f331eab8c57980e6d7e0e64cc2" +} diff --git a/core/deposit/.sqlx/query-1db91bf209069691293eef23a38715c4db000954e0ffb38eccf9d565e0d54c66.json b/core/deposit/.sqlx/query-1db91bf209069691293eef23a38715c4db000954e0ffb38eccf9d565e0d54c66.json new file mode 100644 index 000000000..388afccf9 --- /dev/null +++ b/core/deposit/.sqlx/query-1db91bf209069691293eef23a38715c4db000954e0ffb38eccf9d565e0d54c66.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_deposit_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "1db91bf209069691293eef23a38715c4db000954e0ffb38eccf9d565e0d54c66" +} diff --git a/core/deposit/.sqlx/query-1f4ab93dd25d5e57350e4f9e089562d3988dac58a8d3dd6448c79329fbd2bf50.json b/core/deposit/.sqlx/query-1f4ab93dd25d5e57350e4f9e089562d3988dac58a8d3dd6448c79329fbd2bf50.json new file mode 100644 index 000000000..6110045ff --- /dev/null +++ b/core/deposit/.sqlx/query-1f4ab93dd25d5e57350e4f9e089562d3988dac58a8d3dd6448c79329fbd2bf50.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO deposit_accounts (id, account_holder_id, created_at) VALUES ($1, $2, $3)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "1f4ab93dd25d5e57350e4f9e089562d3988dac58a8d3dd6448c79329fbd2bf50" +} diff --git a/core/deposit/.sqlx/query-210062ee036b0b5c901747bb65466462c4184a00f49b745f596a9a48d2866526.json b/core/deposit/.sqlx/query-210062ee036b0b5c901747bb65466462c4184a00f49b745f596a9a48d2866526.json new file mode 100644 index 000000000..765cc9203 --- /dev/null +++ b/core/deposit/.sqlx/query-210062ee036b0b5c901747bb65466462c4184a00f49b745f596a9a48d2866526.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO policy_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "210062ee036b0b5c901747bb65466462c4184a00f49b745f596a9a48d2866526" +} diff --git a/core/deposit/.sqlx/query-22d881277f4f5ab30cfa52a8f741668f041e396940292012dec1f722395723d4.json b/core/deposit/.sqlx/query-22d881277f4f5ab30cfa52a8f741668f041e396940292012dec1f722395723d4.json new file mode 100644 index 000000000..d3d174181 --- /dev/null +++ b/core/deposit/.sqlx/query-22d881277f4f5ab30cfa52a8f741668f041e396940292012dec1f722395723d4.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO approval_processes (id, process_type, committee_id, policy_id, created_at) VALUES ($1, $2, $3, $4, $5)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "22d881277f4f5ab30cfa52a8f741668f041e396940292012dec1f722395723d4" +} diff --git a/core/deposit/.sqlx/query-253f173128747ab15dfd97869fefe3a4b7ff59391ad86c03652dae9d0a3df5e9.json b/core/deposit/.sqlx/query-253f173128747ab15dfd97869fefe3a4b7ff59391ad86c03652dae9d0a3df5e9.json new file mode 100644 index 000000000..b137b511d --- /dev/null +++ b/core/deposit/.sqlx/query-253f173128747ab15dfd97869fefe3a4b7ff59391ad86c03652dae9d0a3df5e9.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT account_holder_id, id FROM deposit_accounts WHERE ((account_holder_id = $1) AND (COALESCE(id < $3, true))) ORDER BY id DESC LIMIT $2) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "253f173128747ab15dfd97869fefe3a4b7ff59391ad86c03652dae9d0a3df5e9" +} diff --git a/core/deposit/.sqlx/query-2b1d7fa79075434b7de969a0c05930932876aab67e3c7233ade6238f65abae7e.json b/core/deposit/.sqlx/query-2b1d7fa79075434b7de969a0c05930932876aab67e3c7233ade6238f65abae7e.json new file mode 100644 index 000000000..bda393797 --- /dev/null +++ b/core/deposit/.sqlx/query-2b1d7fa79075434b7de969a0c05930932876aab67e3c7233ade6238f65abae7e.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM committees WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "2b1d7fa79075434b7de969a0c05930932876aab67e3c7233ade6238f65abae7e" +} diff --git a/core/deposit/.sqlx/query-2fa6746fe038859c0a60b826981d794d7e148bc365e6c65ddc4e5d6c5118e892.json b/core/deposit/.sqlx/query-2fa6746fe038859c0a60b826981d794d7e148bc365e6c65ddc4e5d6c5118e892.json new file mode 100644 index 000000000..8d1a8084d --- /dev/null +++ b/core/deposit/.sqlx/query-2fa6746fe038859c0a60b826981d794d7e148bc365e6c65ddc4e5d6c5118e892.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO committees (id, name, created_at) VALUES ($1, $2, $3)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "2fa6746fe038859c0a60b826981d794d7e148bc365e6c65ddc4e5d6c5118e892" +} diff --git a/core/deposit/.sqlx/query-3b700518ff9b8645bb55c8228274eb1c8d22b885fc76559381153f00fe5d6997.json b/core/deposit/.sqlx/query-3b700518ff9b8645bb55c8228274eb1c8d22b885fc76559381153f00fe5d6997.json new file mode 100644 index 000000000..577e4b184 --- /dev/null +++ b/core/deposit/.sqlx/query-3b700518ff9b8645bb55c8228274eb1c8d22b885fc76559381153f00fe5d6997.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT committee_id, created_at, id FROM approval_processes WHERE ((committee_id = $1) AND (COALESCE((created_at, id) < ($4, $3), $3 IS NULL))) ORDER BY created_at DESC, id DESC LIMIT $2) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "3b700518ff9b8645bb55c8228274eb1c8d22b885fc76559381153f00fe5d6997" +} diff --git a/core/deposit/.sqlx/query-3f939eb162598958144991a18c4ad01fa5cdac730283ce60b91056aadbc5a30e.json b/core/deposit/.sqlx/query-3f939eb162598958144991a18c4ad01fa5cdac730283ce60b91056aadbc5a30e.json new file mode 100644 index 000000000..69351b7e3 --- /dev/null +++ b/core/deposit/.sqlx/query-3f939eb162598958144991a18c4ad01fa5cdac730283ce60b91056aadbc5a30e.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM policies WHERE id = $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "3f939eb162598958144991a18c4ad01fa5cdac730283ce60b91056aadbc5a30e" +} diff --git a/core/deposit/.sqlx/query-3faa09694d967adc67414ff65a9076b61390cead90ed9009821b5754f6d062a0.json b/core/deposit/.sqlx/query-3faa09694d967adc67414ff65a9076b61390cead90ed9009821b5754f6d062a0.json new file mode 100644 index 000000000..744355ef3 --- /dev/null +++ b/core/deposit/.sqlx/query-3faa09694d967adc67414ff65a9076b61390cead90ed9009821b5754f6d062a0.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM committees i JOIN committee_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "3faa09694d967adc67414ff65a9076b61390cead90ed9009821b5754f6d062a0" +} diff --git a/core/deposit/.sqlx/query-41c8a58184b92cb958da2fbb008cde50de9da8caf62c5c8d8c5c54b5925144b0.json b/core/deposit/.sqlx/query-41c8a58184b92cb958da2fbb008cde50de9da8caf62c5c8d8c5c54b5925144b0.json new file mode 100644 index 000000000..ae9765d7a --- /dev/null +++ b/core/deposit/.sqlx/query-41c8a58184b92cb958da2fbb008cde50de9da8caf62c5c8d8c5c54b5925144b0.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT committee_id, id FROM approval_processes WHERE ((committee_id = $1) AND (COALESCE(id > $3, true))) ORDER BY id ASC LIMIT $2) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "41c8a58184b92cb958da2fbb008cde50de9da8caf62c5c8d8c5c54b5925144b0" +} diff --git a/core/deposit/.sqlx/query-427eff7cb96e2e6229ff1126596883e4dcd306cadd5d96f3d91a50047b91a849.json b/core/deposit/.sqlx/query-427eff7cb96e2e6229ff1126596883e4dcd306cadd5d96f3d91a50047b91a849.json new file mode 100644 index 000000000..52f020376 --- /dev/null +++ b/core/deposit/.sqlx/query-427eff7cb96e2e6229ff1126596883e4dcd306cadd5d96f3d91a50047b91a849.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_deposits WHERE id = $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "427eff7cb96e2e6229ff1126596883e4dcd306cadd5d96f3d91a50047b91a849" +} diff --git a/core/deposit/.sqlx/query-43a7816dc14d728deb7d179c5e862d5c510b70336c69e74e0a0ac6b8381a5759.json b/core/deposit/.sqlx/query-43a7816dc14d728deb7d179c5e862d5c510b70336c69e74e0a0ac6b8381a5759.json new file mode 100644 index 000000000..e6340e31a --- /dev/null +++ b/core/deposit/.sqlx/query-43a7816dc14d728deb7d179c5e862d5c510b70336c69e74e0a0ac6b8381a5759.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: DepositId\", e.sequence, e.event, e.recorded_at FROM core_deposits i JOIN core_deposit_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "43a7816dc14d728deb7d179c5e862d5c510b70336c69e74e0a0ac6b8381a5759" +} diff --git a/core/deposit/.sqlx/query-4695792a24d5b9b4f2784151b66c15412a584727eb684cd18123a4d2c00929e9.json b/core/deposit/.sqlx/query-4695792a24d5b9b4f2784151b66c15412a584727eb684cd18123a4d2c00929e9.json new file mode 100644 index 000000000..dda5454fb --- /dev/null +++ b/core/deposit/.sqlx/query-4695792a24d5b9b4f2784151b66c15412a584727eb684cd18123a4d2c00929e9.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE approval_process_id = $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "4695792a24d5b9b4f2784151b66c15412a584727eb684cd18123a4d2c00929e9" +} diff --git a/core/deposit/.sqlx/query-47ce06b9bc1c72f53524ba80b97201a7014fc209feac8338c3aa03f05e98ace9.json b/core/deposit/.sqlx/query-47ce06b9bc1c72f53524ba80b97201a7014fc209feac8338c3aa03f05e98ace9.json new file mode 100644 index 000000000..3d15b7ad0 --- /dev/null +++ b/core/deposit/.sqlx/query-47ce06b9bc1c72f53524ba80b97201a7014fc209feac8338c3aa03f05e98ace9.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO committee_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "47ce06b9bc1c72f53524ba80b97201a7014fc209feac8338c3aa03f05e98ace9" +} diff --git a/core/deposit/.sqlx/query-47e131061ca46b535e7610767eb5e80026e67ee62235c9c5b2f91ea88f7fdb19.json b/core/deposit/.sqlx/query-47e131061ca46b535e7610767eb5e80026e67ee62235c9c5b2f91ea88f7fdb19.json new file mode 100644 index 000000000..bc225186e --- /dev/null +++ b/core/deposit/.sqlx/query-47e131061ca46b535e7610767eb5e80026e67ee62235c9c5b2f91ea88f7fdb19.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, id FROM core_deposits WHERE ((deposit_account_id = $1) AND (COALESCE(id > $3, true))) ORDER BY id ASC LIMIT $2) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "47e131061ca46b535e7610767eb5e80026e67ee62235c9c5b2f91ea88f7fdb19" +} diff --git a/core/deposit/.sqlx/query-4b6c51381b49631484d7318e49412c2861fb8a6ca78eeb12c99ea56e946e8fd8.json b/core/deposit/.sqlx/query-4b6c51381b49631484d7318e49412c2861fb8a6ca78eeb12c99ea56e946e8fd8.json new file mode 100644 index 000000000..e3ab47346 --- /dev/null +++ b/core/deposit/.sqlx/query-4b6c51381b49631484d7318e49412c2861fb8a6ca78eeb12c99ea56e946e8fd8.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH max_sequence AS (\n SELECT COALESCE(MAX(sequence), 0) AS max FROM persistent_outbox_events\n )\n SELECT\n g.seq AS \"sequence!: EventSequence\",\n e.id AS \"id?\",\n e.payload AS \"payload?\",\n e.recorded_at AS \"recorded_at?\"\n FROM\n generate_series(LEAST($1 + 1, (SELECT max FROM max_sequence)),\n LEAST($1 + $2, (SELECT max FROM max_sequence)))\n AS g(seq)\n LEFT JOIN\n persistent_outbox_events e ON g.seq = e.sequence\n WHERE\n g.seq > $1\n ORDER BY\n g.seq ASC\n LIMIT $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "sequence!: EventSequence", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "id?", + "type_info": "Uuid" + }, + { + "ordinal": 2, + "name": "payload?", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at?", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int4" + ] + }, + "nullable": [ + null, + false, + true, + false + ] + }, + "hash": "4b6c51381b49631484d7318e49412c2861fb8a6ca78eeb12c99ea56e946e8fd8" +} diff --git a/core/deposit/.sqlx/query-4ddaa20ede3df1a493c3a91136250b79c2a69f0ff5938d5e082b86346aeac6c4.json b/core/deposit/.sqlx/query-4ddaa20ede3df1a493c3a91136250b79c2a69f0ff5938d5e082b86346aeac6c4.json new file mode 100644 index 000000000..44c08f4da --- /dev/null +++ b/core/deposit/.sqlx/query-4ddaa20ede3df1a493c3a91136250b79c2a69f0ff5938d5e082b86346aeac6c4.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, created_at, id FROM core_withdrawals WHERE ((deposit_account_id = $1) AND (COALESCE((created_at, id) > ($4, $3), $3 IS NULL))) ORDER BY created_at ASC, id ASC LIMIT $2) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "4ddaa20ede3df1a493c3a91136250b79c2a69f0ff5938d5e082b86346aeac6c4" +} diff --git a/core/deposit/.sqlx/query-56298b5483f52dbc43fdee3f99d183200e6f742ca0956ed5d35e7e64b9facff5.json b/core/deposit/.sqlx/query-56298b5483f52dbc43fdee3f99d183200e6f742ca0956ed5d35e7e64b9facff5.json new file mode 100644 index 000000000..e2bdb8a80 --- /dev/null +++ b/core/deposit/.sqlx/query-56298b5483f52dbc43fdee3f99d183200e6f742ca0956ed5d35e7e64b9facff5.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM policies WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "56298b5483f52dbc43fdee3f99d183200e6f742ca0956ed5d35e7e64b9facff5" +} diff --git a/core/deposit/.sqlx/query-56a93a89179b42b6c18ccfbd9aa6012ca664f55cb601a19e0ced610e5b442296.json b/core/deposit/.sqlx/query-56a93a89179b42b6c18ccfbd9aa6012ca664f55cb601a19e0ced610e5b442296.json new file mode 100644 index 000000000..71459709a --- /dev/null +++ b/core/deposit/.sqlx/query-56a93a89179b42b6c18ccfbd9aa6012ca664f55cb601a19e0ced610e5b442296.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, created_at, id FROM core_deposits WHERE ((deposit_account_id = $1) AND (COALESCE((created_at, id) > ($4, $3), $3 IS NULL))) ORDER BY created_at ASC, id ASC LIMIT $2) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "56a93a89179b42b6c18ccfbd9aa6012ca664f55cb601a19e0ced610e5b442296" +} diff --git a/core/deposit/.sqlx/query-5cf7924a6417fd9d6a1fc4fc373aeac4e1c0e3953425a4e62acc8a8039cbe539.json b/core/deposit/.sqlx/query-5cf7924a6417fd9d6a1fc4fc373aeac4e1c0e3953425a4e62acc8a8039cbe539.json new file mode 100644 index 000000000..550be8e80 --- /dev/null +++ b/core/deposit/.sqlx/query-5cf7924a6417fd9d6a1fc4fc373aeac4e1c0e3953425a4e62acc8a8039cbe539.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_withdrawal_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "5cf7924a6417fd9d6a1fc4fc373aeac4e1c0e3953425a4e62acc8a8039cbe539" +} diff --git a/core/deposit/.sqlx/query-606f56745ea686c3c98655f1ba29c892b469fe2e630d9824372ebb58c22314f2.json b/core/deposit/.sqlx/query-606f56745ea686c3c98655f1ba29c892b469fe2e630d9824372ebb58c22314f2.json new file mode 100644 index 000000000..db1a9fc59 --- /dev/null +++ b/core/deposit/.sqlx/query-606f56745ea686c3c98655f1ba29c892b469fe2e630d9824372ebb58c22314f2.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_withdrawals (id, deposit_account_id, approval_process_id, reference, created_at) VALUES ($1, $2, $3, $4, $5)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid", + "Uuid", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "606f56745ea686c3c98655f1ba29c892b469fe2e630d9824372ebb58c22314f2" +} diff --git a/core/deposit/.sqlx/query-63cc3d4239b25c639a879f8742951066a70b78643536b15c52d3c48e81a3891d.json b/core/deposit/.sqlx/query-63cc3d4239b25c639a879f8742951066a70b78643536b15c52d3c48e81a3891d.json new file mode 100644 index 000000000..55eefd952 --- /dev/null +++ b/core/deposit/.sqlx/query-63cc3d4239b25c639a879f8742951066a70b78643536b15c52d3c48e81a3891d.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM committees WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "63cc3d4239b25c639a879f8742951066a70b78643536b15c52d3c48e81a3891d" +} diff --git a/core/deposit/.sqlx/query-6652182373e14925412ce85f358c64af3a98ec895e1747e2ce6a61221af8c657.json b/core/deposit/.sqlx/query-6652182373e14925412ce85f358c64af3a98ec895e1747e2ce6a61221af8c657.json new file mode 100644 index 000000000..08b2302b0 --- /dev/null +++ b/core/deposit/.sqlx/query-6652182373e14925412ce85f358c64af3a98ec895e1747e2ce6a61221af8c657.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, created_at, id FROM core_deposits WHERE ((deposit_account_id = $1) AND (COALESCE((created_at, id) < ($4, $3), $3 IS NULL))) ORDER BY created_at DESC, id DESC LIMIT $2) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "6652182373e14925412ce85f358c64af3a98ec895e1747e2ce6a61221af8c657" +} diff --git a/core/deposit/.sqlx/query-66660428ec43617b9017f0f4d08630c3934c48c74e14bd08fd81d70880c5ae65.json b/core/deposit/.sqlx/query-66660428ec43617b9017f0f4d08630c3934c48c74e14bd08fd81d70880c5ae65.json new file mode 100644 index 000000000..b7dbe210c --- /dev/null +++ b/core/deposit/.sqlx/query-66660428ec43617b9017f0f4d08630c3934c48c74e14bd08fd81d70880c5ae65.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO deposit_account_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "66660428ec43617b9017f0f4d08630c3934c48c74e14bd08fd81d70880c5ae65" +} diff --git a/core/deposit/.sqlx/query-694f1dd65b5724fcf6937d56b1770c7823d9f85c17f9d98862e425477387ae89.json b/core/deposit/.sqlx/query-694f1dd65b5724fcf6937d56b1770c7823d9f85c17f9d98862e425477387ae89.json new file mode 100644 index 000000000..2c85aa2e3 --- /dev/null +++ b/core/deposit/.sqlx/query-694f1dd65b5724fcf6937d56b1770c7823d9f85c17f9d98862e425477387ae89.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM committees WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "694f1dd65b5724fcf6937d56b1770c7823d9f85c17f9d98862e425477387ae89" +} diff --git a/core/deposit/.sqlx/query-697f26ecc715a804258dfb0112308539202abe4dd3af28d528bedcd09b551cab.json b/core/deposit/.sqlx/query-697f26ecc715a804258dfb0112308539202abe4dd3af28d528bedcd09b551cab.json new file mode 100644 index 000000000..c76e1cd1e --- /dev/null +++ b/core/deposit/.sqlx/query-697f26ecc715a804258dfb0112308539202abe4dd3af28d528bedcd09b551cab.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_deposits (id, deposit_account_id, reference, created_at) VALUES ($1, $2, $3, $4)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "697f26ecc715a804258dfb0112308539202abe4dd3af28d528bedcd09b551cab" +} diff --git a/core/deposit/.sqlx/query-6c035629a0b60e177f54c64ae17f1fb9fee700a7a55f5fd658e9a7f8839ed3a2.json b/core/deposit/.sqlx/query-6c035629a0b60e177f54c64ae17f1fb9fee700a7a55f5fd658e9a7f8839ed3a2.json new file mode 100644 index 000000000..6b19384b0 --- /dev/null +++ b/core/deposit/.sqlx/query-6c035629a0b60e177f54c64ae17f1fb9fee700a7a55f5fd658e9a7f8839ed3a2.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE policy_id = $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "6c035629a0b60e177f54c64ae17f1fb9fee700a7a55f5fd658e9a7f8839ed3a2" +} diff --git a/core/deposit/.sqlx/query-6f45f539edff97cdbcdf8ba879e33fd48abe353bbc92cb690d98dcf6f641750f.json b/core/deposit/.sqlx/query-6f45f539edff97cdbcdf8ba879e33fd48abe353bbc92cb690d98dcf6f641750f.json new file mode 100644 index 000000000..947523020 --- /dev/null +++ b/core/deposit/.sqlx/query-6f45f539edff97cdbcdf8ba879e33fd48abe353bbc92cb690d98dcf6f641750f.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, id FROM core_withdrawals WHERE ((deposit_account_id = $1) AND (COALESCE(id < $3, true))) ORDER BY id DESC LIMIT $2) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "6f45f539edff97cdbcdf8ba879e33fd48abe353bbc92cb690d98dcf6f641750f" +} diff --git a/core/deposit/.sqlx/query-70a9ee61b82ceea3c197d4aae1fd017d19410792c60ffcb01edaaca1dfeae2ea.json b/core/deposit/.sqlx/query-70a9ee61b82ceea3c197d4aae1fd017d19410792c60ffcb01edaaca1dfeae2ea.json new file mode 100644 index 000000000..c18349ed1 --- /dev/null +++ b/core/deposit/.sqlx/query-70a9ee61b82ceea3c197d4aae1fd017d19410792c60ffcb01edaaca1dfeae2ea.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "70a9ee61b82ceea3c197d4aae1fd017d19410792c60ffcb01edaaca1dfeae2ea" +} diff --git a/core/deposit/.sqlx/query-73042ca58753f878ef7da169e3d5edb8ac006bf8b55ff7a6f3844aa60ae2eebc.json b/core/deposit/.sqlx/query-73042ca58753f878ef7da169e3d5edb8ac006bf8b55ff7a6f3844aa60ae2eebc.json new file mode 100644 index 000000000..1d702f465 --- /dev/null +++ b/core/deposit/.sqlx/query-73042ca58753f878ef7da169e3d5edb8ac006bf8b55ff7a6f3844aa60ae2eebc.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM committees WHERE id = $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "73042ca58753f878ef7da169e3d5edb8ac006bf8b55ff7a6f3844aa60ae2eebc" +} diff --git a/core/deposit/.sqlx/query-75052c2b453721eae52cfaf6e65c9b5067c492748febc14e8e2b40925422eea7.json b/core/deposit/.sqlx/query-75052c2b453721eae52cfaf6e65c9b5067c492748febc14e8e2b40925422eea7.json new file mode 100644 index 000000000..c050398ce --- /dev/null +++ b/core/deposit/.sqlx/query-75052c2b453721eae52cfaf6e65c9b5067c492748febc14e8e2b40925422eea7.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_deposits WHERE deposit_account_id = $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "75052c2b453721eae52cfaf6e65c9b5067c492748febc14e8e2b40925422eea7" +} diff --git a/core/deposit/.sqlx/query-757592f9832c8e1efb9b8dfb0f78868b00c3c0bdc73fe72a03bae7a807139c6b.json b/core/deposit/.sqlx/query-757592f9832c8e1efb9b8dfb0f78868b00c3c0bdc73fe72a03bae7a807139c6b.json new file mode 100644 index 000000000..384262f22 --- /dev/null +++ b/core/deposit/.sqlx/query-757592f9832c8e1efb9b8dfb0f78868b00c3c0bdc73fe72a03bae7a807139c6b.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM core_withdrawals WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "757592f9832c8e1efb9b8dfb0f78868b00c3c0bdc73fe72a03bae7a807139c6b" +} diff --git a/core/deposit/.sqlx/query-769e2b41629abb4c12e1b195dee654423c0b2415cae74021b701cc3ed1a6a72c.json b/core/deposit/.sqlx/query-769e2b41629abb4c12e1b195dee654423c0b2415cae74021b701cc3ed1a6a72c.json new file mode 100644 index 000000000..b22a7fa7c --- /dev/null +++ b/core/deposit/.sqlx/query-769e2b41629abb4c12e1b195dee654423c0b2415cae74021b701cc3ed1a6a72c.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM core_deposits WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "769e2b41629abb4c12e1b195dee654423c0b2415cae74021b701cc3ed1a6a72c" +} diff --git a/core/deposit/.sqlx/query-77441bd6efa7cff0917b00344393de214afa08a8a80cd8fea42bcfcf347dbffe.json b/core/deposit/.sqlx/query-77441bd6efa7cff0917b00344393de214afa08a8a80cd8fea42bcfcf347dbffe.json new file mode 100644 index 000000000..f631d8a53 --- /dev/null +++ b/core/deposit/.sqlx/query-77441bd6efa7cff0917b00344393de214afa08a8a80cd8fea42bcfcf347dbffe.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE id = $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "77441bd6efa7cff0917b00344393de214afa08a8a80cd8fea42bcfcf347dbffe" +} diff --git a/core/deposit/.sqlx/query-77b298409650fb826ef92b5cbc7bc30091a70e30b6615cd1da20f5b2ada92971.json b/core/deposit/.sqlx/query-77b298409650fb826ef92b5cbc7bc30091a70e30b6615cd1da20f5b2ada92971.json new file mode 100644 index 000000000..f9375e0c7 --- /dev/null +++ b/core/deposit/.sqlx/query-77b298409650fb826ef92b5cbc7bc30091a70e30b6615cd1da20f5b2ada92971.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM deposit_accounts WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "77b298409650fb826ef92b5cbc7bc30091a70e30b6615cd1da20f5b2ada92971" +} diff --git a/core/deposit/.sqlx/query-7a03aaa2e73d95b0273bcbfac7fe56cc9e0c427d7c32e6a2e1d9e66f43231623.json b/core/deposit/.sqlx/query-7a03aaa2e73d95b0273bcbfac7fe56cc9e0c427d7c32e6a2e1d9e66f43231623.json new file mode 100644 index 000000000..285f3476a --- /dev/null +++ b/core/deposit/.sqlx/query-7a03aaa2e73d95b0273bcbfac7fe56cc9e0c427d7c32e6a2e1d9e66f43231623.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COALESCE(MAX(sequence), 0) AS \"max!\" FROM persistent_outbox_events", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "max!", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null + ] + }, + "hash": "7a03aaa2e73d95b0273bcbfac7fe56cc9e0c427d7c32e6a2e1d9e66f43231623" +} diff --git a/core/deposit/.sqlx/query-7b0d547dda8c4a6ce921025c2e8dd7c9d0b2bbbda1f62fe3c82e5ada575f1bb6.json b/core/deposit/.sqlx/query-7b0d547dda8c4a6ce921025c2e8dd7c9d0b2bbbda1f62fe3c82e5ada575f1bb6.json new file mode 100644 index 000000000..b2d3f7452 --- /dev/null +++ b/core/deposit/.sqlx/query-7b0d547dda8c4a6ce921025c2e8dd7c9d0b2bbbda1f62fe3c82e5ada575f1bb6.json @@ -0,0 +1,52 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id AS \"id: AuditEntryId\", subject, object, action, authorized, recorded_at\n FROM audit_entries\n WHERE id = ANY($1)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: AuditEntryId", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "subject", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "object", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "action", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "authorized", + "type_info": "Bool" + }, + { + "ordinal": 5, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8Array" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false + ] + }, + "hash": "7b0d547dda8c4a6ce921025c2e8dd7c9d0b2bbbda1f62fe3c82e5ada575f1bb6" +} diff --git a/core/deposit/.sqlx/query-7bebb58c6ae4876c06a021a9865d5b68b491701d52b632de14823dafd5756cd3.json b/core/deposit/.sqlx/query-7bebb58c6ae4876c06a021a9865d5b68b491701d52b632de14823dafd5756cd3.json new file mode 100644 index 000000000..5365985d7 --- /dev/null +++ b/core/deposit/.sqlx/query-7bebb58c6ae4876c06a021a9865d5b68b491701d52b632de14823dafd5756cd3.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM committees WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "7bebb58c6ae4876c06a021a9865d5b68b491701d52b632de14823dafd5756cd3" +} diff --git a/core/deposit/.sqlx/query-80de7b594db20b2c5f17d3b803fb44ec8e0639c0f896b11baf340f2092677129.json b/core/deposit/.sqlx/query-80de7b594db20b2c5f17d3b803fb44ec8e0639c0f896b11baf340f2092677129.json new file mode 100644 index 000000000..c8aa136cc --- /dev/null +++ b/core/deposit/.sqlx/query-80de7b594db20b2c5f17d3b803fb44ec8e0639c0f896b11baf340f2092677129.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_deposits WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "80de7b594db20b2c5f17d3b803fb44ec8e0639c0f896b11baf340f2092677129" +} diff --git a/core/deposit/.sqlx/query-86f9a2c0b430230f05fbd7ad65ad3c9d0907d654138ba2a62cb9bee521fd4a03.json b/core/deposit/.sqlx/query-86f9a2c0b430230f05fbd7ad65ad3c9d0907d654138ba2a62cb9bee521fd4a03.json new file mode 100644 index 000000000..5328dc404 --- /dev/null +++ b/core/deposit/.sqlx/query-86f9a2c0b430230f05fbd7ad65ad3c9d0907d654138ba2a62cb9bee521fd4a03.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM approval_processes WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "86f9a2c0b430230f05fbd7ad65ad3c9d0907d654138ba2a62cb9bee521fd4a03" +} diff --git a/core/deposit/.sqlx/query-8ea5f8d69ed4ad9113e4908cf740743f30dfbe27e5432c6587968ea0c2b73369.json b/core/deposit/.sqlx/query-8ea5f8d69ed4ad9113e4908cf740743f30dfbe27e5432c6587968ea0c2b73369.json new file mode 100644 index 000000000..8c4ce1ff9 --- /dev/null +++ b/core/deposit/.sqlx/query-8ea5f8d69ed4ad9113e4908cf740743f30dfbe27e5432c6587968ea0c2b73369.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM deposit_accounts WHERE id = $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "8ea5f8d69ed4ad9113e4908cf740743f30dfbe27e5432c6587968ea0c2b73369" +} diff --git a/core/deposit/.sqlx/query-8eb956fdaf23f5438306641d34b6aab8b7776927ff58875009b77754073abb64.json b/core/deposit/.sqlx/query-8eb956fdaf23f5438306641d34b6aab8b7776927ff58875009b77754073abb64.json new file mode 100644 index 000000000..29bf3909a --- /dev/null +++ b/core/deposit/.sqlx/query-8eb956fdaf23f5438306641d34b6aab8b7776927ff58875009b77754073abb64.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM policies WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "8eb956fdaf23f5438306641d34b6aab8b7776927ff58875009b77754073abb64" +} diff --git a/core/deposit/.sqlx/query-8f1fda3b0a2a441736e6a2a540cee908b0c2e2db176cdc639192d4e887ebd4a3.json b/core/deposit/.sqlx/query-8f1fda3b0a2a441736e6a2a540cee908b0c2e2db176cdc639192d4e887ebd4a3.json new file mode 100644 index 000000000..9179fa2eb --- /dev/null +++ b/core/deposit/.sqlx/query-8f1fda3b0a2a441736e6a2a540cee908b0c2e2db176cdc639192d4e887ebd4a3.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE reference = $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "8f1fda3b0a2a441736e6a2a540cee908b0c2e2db176cdc639192d4e887ebd4a3" +} diff --git a/core/deposit/.sqlx/query-8fea8776f584e7d77a1605903ba9f749f58ae1e85d4cab247dde3caafa24237e.json b/core/deposit/.sqlx/query-8fea8776f584e7d77a1605903ba9f749f58ae1e85d4cab247dde3caafa24237e.json new file mode 100644 index 000000000..9badd741a --- /dev/null +++ b/core/deposit/.sqlx/query-8fea8776f584e7d77a1605903ba9f749f58ae1e85d4cab247dde3caafa24237e.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM approval_processes WHERE (COALESCE((created_at, id) < ($3, $2), $2 IS NULL)) ORDER BY created_at DESC, id DESC LIMIT $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "8fea8776f584e7d77a1605903ba9f749f58ae1e85d4cab247dde3caafa24237e" +} diff --git a/core/deposit/.sqlx/query-907e360e9cf644967b883943c7975388153d6f0cb0f91e4da0741427b00deea4.json b/core/deposit/.sqlx/query-907e360e9cf644967b883943c7975388153d6f0cb0f91e4da0741427b00deea4.json new file mode 100644 index 000000000..cac5c07aa --- /dev/null +++ b/core/deposit/.sqlx/query-907e360e9cf644967b883943c7975388153d6f0cb0f91e4da0741427b00deea4.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE deposit_account_id = $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "907e360e9cf644967b883943c7975388153d6f0cb0f91e4da0741427b00deea4" +} diff --git a/core/deposit/.sqlx/query-91debda9c1f7653b7bcb38a311d0f665f05d8fb39a8f371b9bbdcd4d35b2280e.json b/core/deposit/.sqlx/query-91debda9c1f7653b7bcb38a311d0f665f05d8fb39a8f371b9bbdcd4d35b2280e.json new file mode 100644 index 000000000..2643d87f1 --- /dev/null +++ b/core/deposit/.sqlx/query-91debda9c1f7653b7bcb38a311d0f665f05d8fb39a8f371b9bbdcd4d35b2280e.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM core_withdrawals WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "91debda9c1f7653b7bcb38a311d0f665f05d8fb39a8f371b9bbdcd4d35b2280e" +} diff --git a/core/deposit/.sqlx/query-96cb61b0eda9cb5900206353bffffd14752b73ae0496b0e552d63f242a7d0eee.json b/core/deposit/.sqlx/query-96cb61b0eda9cb5900206353bffffd14752b73ae0496b0e552d63f242a7d0eee.json new file mode 100644 index 000000000..5d3b2ece3 --- /dev/null +++ b/core/deposit/.sqlx/query-96cb61b0eda9cb5900206353bffffd14752b73ae0496b0e552d63f242a7d0eee.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO committee_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "96cb61b0eda9cb5900206353bffffd14752b73ae0496b0e552d63f242a7d0eee" +} diff --git a/core/deposit/.sqlx/query-9af6eb14d4bb659fbfc6511756490722479c365d4760a490ec136a1ef9ebb979.json b/core/deposit/.sqlx/query-9af6eb14d4bb659fbfc6511756490722479c365d4760a490ec136a1ef9ebb979.json new file mode 100644 index 000000000..14fc40a50 --- /dev/null +++ b/core/deposit/.sqlx/query-9af6eb14d4bb659fbfc6511756490722479c365d4760a490ec136a1ef9ebb979.json @@ -0,0 +1,31 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO audit_entries (subject, object, action, authorized)\n VALUES ($1, $2, $3, $4)\n RETURNING id, subject\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "subject", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Varchar", + "Bool" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "9af6eb14d4bb659fbfc6511756490722479c365d4760a490ec136a1ef9ebb979" +} diff --git a/core/deposit/.sqlx/query-a0c05c6256eb12980957aa7060754488b0ab7620c0df794b0140d4cd29728aba.json b/core/deposit/.sqlx/query-a0c05c6256eb12980957aa7060754488b0ab7620c0df794b0140d4cd29728aba.json new file mode 100644 index 000000000..f91ae37be --- /dev/null +++ b/core/deposit/.sqlx/query-a0c05c6256eb12980957aa7060754488b0ab7620c0df794b0140d4cd29728aba.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE committee_id = $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "a0c05c6256eb12980957aa7060754488b0ab7620c0df794b0140d4cd29728aba" +} diff --git a/core/deposit/.sqlx/query-a1550c7ad93b614b9aa3e1d7800d5856b23aab7bad820f5cb8ff7c9869cb02ad.json b/core/deposit/.sqlx/query-a1550c7ad93b614b9aa3e1d7800d5856b23aab7bad820f5cb8ff7c9869cb02ad.json new file mode 100644 index 000000000..3e5aef4c3 --- /dev/null +++ b/core/deposit/.sqlx/query-a1550c7ad93b614b9aa3e1d7800d5856b23aab7bad820f5cb8ff7c9869cb02ad.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM policies WHERE process_type = $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "a1550c7ad93b614b9aa3e1d7800d5856b23aab7bad820f5cb8ff7c9869cb02ad" +} diff --git a/core/deposit/.sqlx/query-a1dcaba56af024322df454768c2cef9cd0fbcf91128bb4e2a372a16e3b9b8c69.json b/core/deposit/.sqlx/query-a1dcaba56af024322df454768c2cef9cd0fbcf91128bb4e2a372a16e3b9b8c69.json new file mode 100644 index 000000000..49d89a244 --- /dev/null +++ b/core/deposit/.sqlx/query-a1dcaba56af024322df454768c2cef9cd0fbcf91128bb4e2a372a16e3b9b8c69.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO persistent_outbox_events (sequence)\n SELECT unnest($1::bigint[]) AS sequence\n ON CONFLICT (sequence) DO UPDATE\n SET sequence = EXCLUDED.sequence\n RETURNING id, sequence AS \"sequence!: EventSequence\", payload, recorded_at\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence!: EventSequence", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "payload", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8Array" + ] + }, + "nullable": [ + false, + false, + true, + false + ] + }, + "hash": "a1dcaba56af024322df454768c2cef9cd0fbcf91128bb4e2a372a16e3b9b8c69" +} diff --git a/core/deposit/.sqlx/query-a27bea0d43b3ea7c807ef1a668378640d5eac3049bd61d937bd657b24601a3f0.json b/core/deposit/.sqlx/query-a27bea0d43b3ea7c807ef1a668378640d5eac3049bd61d937bd657b24601a3f0.json new file mode 100644 index 000000000..6380b4539 --- /dev/null +++ b/core/deposit/.sqlx/query-a27bea0d43b3ea7c807ef1a668378640d5eac3049bd61d937bd657b24601a3f0.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, created_at, id FROM core_withdrawals WHERE ((deposit_account_id = $1) AND (COALESCE((created_at, id) < ($4, $3), $3 IS NULL))) ORDER BY created_at DESC, id DESC LIMIT $2) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "a27bea0d43b3ea7c807ef1a668378640d5eac3049bd61d937bd657b24601a3f0" +} diff --git a/core/deposit/.sqlx/query-a675bedaa34fd80880639edf6841764d2ca6b3139949b6e19c42054acaf0fd85.json b/core/deposit/.sqlx/query-a675bedaa34fd80880639edf6841764d2ca6b3139949b6e19c42054acaf0fd85.json new file mode 100644 index 000000000..ae0c22d8b --- /dev/null +++ b/core/deposit/.sqlx/query-a675bedaa34fd80880639edf6841764d2ca6b3139949b6e19c42054acaf0fd85.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE process_type = $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "a675bedaa34fd80880639edf6841764d2ca6b3139949b6e19c42054acaf0fd85" +} diff --git a/core/deposit/.sqlx/query-a6fae2f669eeb47bb3bf3f098bea0f41f5b7c3475ca4794739e41332a36d106f.json b/core/deposit/.sqlx/query-a6fae2f669eeb47bb3bf3f098bea0f41f5b7c3475ca4794739e41332a36d106f.json new file mode 100644 index 000000000..1d0a9782b --- /dev/null +++ b/core/deposit/.sqlx/query-a6fae2f669eeb47bb3bf3f098bea0f41f5b7c3475ca4794739e41332a36d106f.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE core_withdrawals SET reference = $2 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "a6fae2f669eeb47bb3bf3f098bea0f41f5b7c3475ca4794739e41332a36d106f" +} diff --git a/core/deposit/.sqlx/query-aad40f81335198b18a07d489f9af88f89c7e55ae4c151d8f1ca0c90576d3907d.json b/core/deposit/.sqlx/query-aad40f81335198b18a07d489f9af88f89c7e55ae4c151d8f1ca0c90576d3907d.json new file mode 100644 index 000000000..e061b7294 --- /dev/null +++ b/core/deposit/.sqlx/query-aad40f81335198b18a07d489f9af88f89c7e55ae4c151d8f1ca0c90576d3907d.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: PolicyId\", e.sequence, e.event, e.recorded_at FROM policies i JOIN policy_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "aad40f81335198b18a07d489f9af88f89c7e55ae4c151d8f1ca0c90576d3907d" +} diff --git a/core/deposit/.sqlx/query-ac632e983b85db1bbe41afce033b2571478925ed0183338dd0d1fdfffe5dfc65.json b/core/deposit/.sqlx/query-ac632e983b85db1bbe41afce033b2571478925ed0183338dd0d1fdfffe5dfc65.json new file mode 100644 index 000000000..64b484cfe --- /dev/null +++ b/core/deposit/.sqlx/query-ac632e983b85db1bbe41afce033b2571478925ed0183338dd0d1fdfffe5dfc65.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO policy_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "ac632e983b85db1bbe41afce033b2571478925ed0183338dd0d1fdfffe5dfc65" +} diff --git a/core/deposit/.sqlx/query-aff13ff30fc3d2db3488a7670ba7f88a5c9be11f7687a9ab1f0629f7f46d8f5c.json b/core/deposit/.sqlx/query-aff13ff30fc3d2db3488a7670ba7f88a5c9be11f7687a9ab1f0629f7f46d8f5c.json new file mode 100644 index 000000000..8bc50cdc0 --- /dev/null +++ b/core/deposit/.sqlx/query-aff13ff30fc3d2db3488a7670ba7f88a5c9be11f7687a9ab1f0629f7f46d8f5c.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM policies WHERE committee_id = $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "aff13ff30fc3d2db3488a7670ba7f88a5c9be11f7687a9ab1f0629f7f46d8f5c" +} diff --git a/core/deposit/.sqlx/query-b746b062c9f0b14efec550715d221aa42c5879711359aa24e1de89d190303442.json b/core/deposit/.sqlx/query-b746b062c9f0b14efec550715d221aa42c5879711359aa24e1de89d190303442.json new file mode 100644 index 000000000..3b366c1b5 --- /dev/null +++ b/core/deposit/.sqlx/query-b746b062c9f0b14efec550715d221aa42c5879711359aa24e1de89d190303442.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO approval_process_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "b746b062c9f0b14efec550715d221aa42c5879711359aa24e1de89d190303442" +} diff --git a/core/deposit/.sqlx/query-bd4cdd0f1e5e2d5a9d25e162dcb12aaf3a0cc3b6c3fdc268a2d38a558310a957.json b/core/deposit/.sqlx/query-bd4cdd0f1e5e2d5a9d25e162dcb12aaf3a0cc3b6c3fdc268a2d38a558310a957.json new file mode 100644 index 000000000..c0be39a36 --- /dev/null +++ b/core/deposit/.sqlx/query-bd4cdd0f1e5e2d5a9d25e162dcb12aaf3a0cc3b6c3fdc268a2d38a558310a957.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE policies SET process_type = $2, committee_id = $3 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "bd4cdd0f1e5e2d5a9d25e162dcb12aaf3a0cc3b6c3fdc268a2d38a558310a957" +} diff --git a/core/deposit/.sqlx/query-bd95c4f0035427d576ce6870ff35c376cab226ee9072da6069e0a119ef75fc2c.json b/core/deposit/.sqlx/query-bd95c4f0035427d576ce6870ff35c376cab226ee9072da6069e0a119ef75fc2c.json new file mode 100644 index 000000000..0e7e5da20 --- /dev/null +++ b/core/deposit/.sqlx/query-bd95c4f0035427d576ce6870ff35c376cab226ee9072da6069e0a119ef75fc2c.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_withdrawal_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "bd95c4f0035427d576ce6870ff35c376cab226ee9072da6069e0a119ef75fc2c" +} diff --git a/core/deposit/.sqlx/query-be503ebd92a55095d55f425717738f6931baa191d2469f30a09b76acab2bbe32.json b/core/deposit/.sqlx/query-be503ebd92a55095d55f425717738f6931baa191d2469f30a09b76acab2bbe32.json new file mode 100644 index 000000000..5122b8a19 --- /dev/null +++ b/core/deposit/.sqlx/query-be503ebd92a55095d55f425717738f6931baa191d2469f30a09b76acab2bbe32.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE core_deposits SET reference = $2 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "be503ebd92a55095d55f425717738f6931baa191d2469f30a09b76acab2bbe32" +} diff --git a/core/deposit/.sqlx/query-beb47657381fba7a11470b3f22ac2304a2d9a492630adae2e7c089cf02f6490a.json b/core/deposit/.sqlx/query-beb47657381fba7a11470b3f22ac2304a2d9a492630adae2e7c089cf02f6490a.json new file mode 100644 index 000000000..fc1ef73bc --- /dev/null +++ b/core/deposit/.sqlx/query-beb47657381fba7a11470b3f22ac2304a2d9a492630adae2e7c089cf02f6490a.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM committees WHERE name = $1) SELECT i.id AS \"entity_id: CommitteeId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN committee_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: CommitteeId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "beb47657381fba7a11470b3f22ac2304a2d9a492630adae2e7c089cf02f6490a" +} diff --git a/core/deposit/.sqlx/query-c231caf2cdfc7a61e91f230ee1a02672d8159fb2bff2aa35be28a5193febea36.json b/core/deposit/.sqlx/query-c231caf2cdfc7a61e91f230ee1a02672d8159fb2bff2aa35be28a5193febea36.json new file mode 100644 index 000000000..6ea7cf34e --- /dev/null +++ b/core/deposit/.sqlx/query-c231caf2cdfc7a61e91f230ee1a02672d8159fb2bff2aa35be28a5193febea36.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_deposits WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "c231caf2cdfc7a61e91f230ee1a02672d8159fb2bff2aa35be28a5193febea36" +} diff --git a/core/deposit/.sqlx/query-cc6402da73a5a1ab26212376f75dd1227bc43f97be6382fa23fe08f9a1d5a585.json b/core/deposit/.sqlx/query-cc6402da73a5a1ab26212376f75dd1227bc43f97be6382fa23fe08f9a1d5a585.json new file mode 100644 index 000000000..d0b957116 --- /dev/null +++ b/core/deposit/.sqlx/query-cc6402da73a5a1ab26212376f75dd1227bc43f97be6382fa23fe08f9a1d5a585.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "cc6402da73a5a1ab26212376f75dd1227bc43f97be6382fa23fe08f9a1d5a585" +} diff --git a/core/deposit/.sqlx/query-cfde9407b814888676bae2c43c29791052da1117559c851b9c003fe2c4483c19.json b/core/deposit/.sqlx/query-cfde9407b814888676bae2c43c29791052da1117559c851b9c003fe2c4483c19.json new file mode 100644 index 000000000..c7b6647b4 --- /dev/null +++ b/core/deposit/.sqlx/query-cfde9407b814888676bae2c43c29791052da1117559c851b9c003fe2c4483c19.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM deposit_accounts i JOIN deposit_account_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "cfde9407b814888676bae2c43c29791052da1117559c851b9c003fe2c4483c19" +} diff --git a/core/deposit/.sqlx/query-d17a8eecb086b7593ee3e83c3a3576dcdcabb95d9c559c34d62547e3d36ac2fa.json b/core/deposit/.sqlx/query-d17a8eecb086b7593ee3e83c3a3576dcdcabb95d9c559c34d62547e3d36ac2fa.json new file mode 100644 index 000000000..4645e5ed6 --- /dev/null +++ b/core/deposit/.sqlx/query-d17a8eecb086b7593ee3e83c3a3576dcdcabb95d9c559c34d62547e3d36ac2fa.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT account_holder_id, created_at, id FROM deposit_accounts WHERE ((account_holder_id = $1) AND (COALESCE((created_at, id) < ($4, $3), $3 IS NULL))) ORDER BY created_at DESC, id DESC LIMIT $2) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.created_at desc, i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "d17a8eecb086b7593ee3e83c3a3576dcdcabb95d9c559c34d62547e3d36ac2fa" +} diff --git a/core/deposit/.sqlx/query-d316bf8d73764c5b013048816f51df5eef2f87e6f57403e9cf8ad809d8c6de5f.json b/core/deposit/.sqlx/query-d316bf8d73764c5b013048816f51df5eef2f87e6f57403e9cf8ad809d8c6de5f.json new file mode 100644 index 000000000..cc7d2c567 --- /dev/null +++ b/core/deposit/.sqlx/query-d316bf8d73764c5b013048816f51df5eef2f87e6f57403e9cf8ad809d8c6de5f.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT deposit_account_id, id FROM core_withdrawals WHERE ((deposit_account_id = $1) AND (COALESCE(id > $3, true))) ORDER BY id ASC LIMIT $2) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "d316bf8d73764c5b013048816f51df5eef2f87e6f57403e9cf8ad809d8c6de5f" +} diff --git a/core/deposit/.sqlx/query-d5e34d8ca71038cafe1ad05732e698a485634eac2d60ad20fe61bce9b4b92041.json b/core/deposit/.sqlx/query-d5e34d8ca71038cafe1ad05732e698a485634eac2d60ad20fe61bce9b4b92041.json new file mode 100644 index 000000000..2a60e2d14 --- /dev/null +++ b/core/deposit/.sqlx/query-d5e34d8ca71038cafe1ad05732e698a485634eac2d60ad20fe61bce9b4b92041.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM approval_processes WHERE (COALESCE(id > $2, true)) ORDER BY id ASC LIMIT $1) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "d5e34d8ca71038cafe1ad05732e698a485634eac2d60ad20fe61bce9b4b92041" +} diff --git a/core/deposit/.sqlx/query-d72800579d235eb5cdf731a6678f1b3ded0740f414586241064c580a06378367.json b/core/deposit/.sqlx/query-d72800579d235eb5cdf731a6678f1b3ded0740f414586241064c580a06378367.json new file mode 100644 index 000000000..ff05f0821 --- /dev/null +++ b/core/deposit/.sqlx/query-d72800579d235eb5cdf731a6678f1b3ded0740f414586241064c580a06378367.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT created_at, id FROM policies WHERE (COALESCE((created_at, id) > ($3, $2), $2 IS NULL)) ORDER BY created_at ASC, id ASC LIMIT $1) SELECT i.id AS \"entity_id: PolicyId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN policy_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: PolicyId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "d72800579d235eb5cdf731a6678f1b3ded0740f414586241064c580a06378367" +} diff --git a/core/deposit/.sqlx/query-d7b4e73ae21ba6dbb23590862c2e2199fa385a0b2fd7edaf775118d92c1f574e.json b/core/deposit/.sqlx/query-d7b4e73ae21ba6dbb23590862c2e2199fa385a0b2fd7edaf775118d92c1f574e.json new file mode 100644 index 000000000..6a88c4cfc --- /dev/null +++ b/core/deposit/.sqlx/query-d7b4e73ae21ba6dbb23590862c2e2199fa385a0b2fd7edaf775118d92c1f574e.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE committees SET name = $2 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "d7b4e73ae21ba6dbb23590862c2e2199fa385a0b2fd7edaf775118d92c1f574e" +} diff --git a/core/deposit/.sqlx/query-d904610a418a5ac37f82313e0a1cfbc2697554a02545749dbf398705bee034f1.json b/core/deposit/.sqlx/query-d904610a418a5ac37f82313e0a1cfbc2697554a02545749dbf398705bee034f1.json new file mode 100644 index 000000000..c6454531d --- /dev/null +++ b/core/deposit/.sqlx/query-d904610a418a5ac37f82313e0a1cfbc2697554a02545749dbf398705bee034f1.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO deposit_account_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "d904610a418a5ac37f82313e0a1cfbc2697554a02545749dbf398705bee034f1" +} diff --git a/core/deposit/.sqlx/query-da8bde1919fb0a4471ed9bed8b81050c40e68e8028cb4d118f4ad5c881e09081.json b/core/deposit/.sqlx/query-da8bde1919fb0a4471ed9bed8b81050c40e68e8028cb4d118f4ad5c881e09081.json new file mode 100644 index 000000000..d0c5c79c7 --- /dev/null +++ b/core/deposit/.sqlx/query-da8bde1919fb0a4471ed9bed8b81050c40e68e8028cb4d118f4ad5c881e09081.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH new_events AS (\n INSERT INTO persistent_outbox_events (payload)\n SELECT unnest($1::jsonb[]) AS payload\n RETURNING id AS \"id: OutboxEventId\", sequence AS \"sequence: EventSequence\", recorded_at\n )\n SELECT * FROM new_events\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: OutboxEventId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence: EventSequence", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "JsonbArray" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "da8bde1919fb0a4471ed9bed8b81050c40e68e8028cb4d118f4ad5c881e09081" +} diff --git a/core/deposit/.sqlx/query-dbe4ece20e9ec7b11016522a24e613008b81814b9c099b1fa62f3885debeae42.json b/core/deposit/.sqlx/query-dbe4ece20e9ec7b11016522a24e613008b81814b9c099b1fa62f3885debeae42.json new file mode 100644 index 000000000..9723add52 --- /dev/null +++ b/core/deposit/.sqlx/query-dbe4ece20e9ec7b11016522a24e613008b81814b9c099b1fa62f3885debeae42.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE id = $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "dbe4ece20e9ec7b11016522a24e613008b81814b9c099b1fa62f3885debeae42" +} diff --git a/core/deposit/.sqlx/query-de8c9894cbf2908e0749d0c267ab52cd912d85a1dce2e20ef9b16c1d7a16d60c.json b/core/deposit/.sqlx/query-de8c9894cbf2908e0749d0c267ab52cd912d85a1dce2e20ef9b16c1d7a16d60c.json new file mode 100644 index 000000000..ca15b5dbc --- /dev/null +++ b/core/deposit/.sqlx/query-de8c9894cbf2908e0749d0c267ab52cd912d85a1dce2e20ef9b16c1d7a16d60c.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO approval_process_events (id, recorded_at, sequence, event_type, event) SELECT unnested.id, $1, unnested.sequence, unnested.event_type, unnested.event FROM UNNEST($2::UUID[], $3::INT[], $4::TEXT[], $5::JSONB[]) AS unnested(id, sequence, event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "UuidArray", + "Int4Array", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "de8c9894cbf2908e0749d0c267ab52cd912d85a1dce2e20ef9b16c1d7a16d60c" +} diff --git a/core/deposit/.sqlx/query-df0eb4298a26ac09dca4d645e42de3db5fbd5b24ad2c99a6bb4183c5c6f86d43.json b/core/deposit/.sqlx/query-df0eb4298a26ac09dca4d645e42de3db5fbd5b24ad2c99a6bb4183c5c6f86d43.json new file mode 100644 index 000000000..ea9b7f2a6 --- /dev/null +++ b/core/deposit/.sqlx/query-df0eb4298a26ac09dca4d645e42de3db5fbd5b24ad2c99a6bb4183c5c6f86d43.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM deposit_accounts WHERE account_holder_id = $1) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "df0eb4298a26ac09dca4d645e42de3db5fbd5b24ad2c99a6bb4183c5c6f86d43" +} diff --git a/core/deposit/.sqlx/query-e26f1c624922b283d07e3f92556be689d2012aef602e07a00c31c774a7bf78a9.json b/core/deposit/.sqlx/query-e26f1c624922b283d07e3f92556be689d2012aef602e07a00c31c774a7bf78a9.json new file mode 100644 index 000000000..6248a0050 --- /dev/null +++ b/core/deposit/.sqlx/query-e26f1c624922b283d07e3f92556be689d2012aef602e07a00c31c774a7bf78a9.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT committee_id, id FROM approval_processes WHERE ((committee_id = $1) AND (COALESCE(id < $3, true))) ORDER BY id DESC LIMIT $2) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "e26f1c624922b283d07e3f92556be689d2012aef602e07a00c31c774a7bf78a9" +} diff --git a/core/deposit/.sqlx/query-e30cab1a790ff1dfce307ae2f174d551f322a1d72fd2cf639685a1a2cf4cbd3f.json b/core/deposit/.sqlx/query-e30cab1a790ff1dfce307ae2f174d551f322a1d72fd2cf639685a1a2cf4cbd3f.json new file mode 100644 index 000000000..480c04811 --- /dev/null +++ b/core/deposit/.sqlx/query-e30cab1a790ff1dfce307ae2f174d551f322a1d72fd2cf639685a1a2cf4cbd3f.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO core_deposit_events (id, recorded_at, sequence, event_type, event) SELECT $1, $2, ROW_NUMBER() OVER () + $3, unnested.event_type, unnested.event FROM UNNEST($4::text[], $5::jsonb[]) AS unnested(event_type, event)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Timestamptz", + "Int8", + "TextArray", + "JsonbArray" + ] + }, + "nullable": [] + }, + "hash": "e30cab1a790ff1dfce307ae2f174d551f322a1d72fd2cf639685a1a2cf4cbd3f" +} diff --git a/core/deposit/.sqlx/query-e97961667c6ff7b1acc0ef7acad4a25dd7767f44f9f0daef9aa1d0ab6c553a0b.json b/core/deposit/.sqlx/query-e97961667c6ff7b1acc0ef7acad4a25dd7767f44f9f0daef9aa1d0ab6c553a0b.json new file mode 100644 index 000000000..1a471d8ee --- /dev/null +++ b/core/deposit/.sqlx/query-e97961667c6ff7b1acc0ef7acad4a25dd7767f44f9f0daef9aa1d0ab6c553a0b.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT committee_id, created_at, id FROM approval_processes WHERE ((committee_id = $1) AND (COALESCE((created_at, id) > ($4, $3), $3 IS NULL))) ORDER BY created_at ASC, id ASC LIMIT $2) SELECT i.id AS \"entity_id: ApprovalProcessId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN approval_process_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: ApprovalProcessId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "e97961667c6ff7b1acc0ef7acad4a25dd7767f44f9f0daef9aa1d0ab6c553a0b" +} diff --git a/core/deposit/.sqlx/query-e99ee286fc20a1957a2bcff1c70808d7bc6b8ae881c6d445bec38d79a6a032af.json b/core/deposit/.sqlx/query-e99ee286fc20a1957a2bcff1c70808d7bc6b8ae881c6d445bec38d79a6a032af.json new file mode 100644 index 000000000..a6564e359 --- /dev/null +++ b/core/deposit/.sqlx/query-e99ee286fc20a1957a2bcff1c70808d7bc6b8ae881c6d445bec38d79a6a032af.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT account_holder_id, id FROM deposit_accounts WHERE ((account_holder_id = $1) AND (COALESCE(id > $3, true))) ORDER BY id ASC LIMIT $2) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "e99ee286fc20a1957a2bcff1c70808d7bc6b8ae881c6d445bec38d79a6a032af" +} diff --git a/core/deposit/.sqlx/query-f3fc3e97653e968b7706ad72dbf9ecd1acc99957b14837f4cd747b9f26b3c02c.json b/core/deposit/.sqlx/query-f3fc3e97653e968b7706ad72dbf9ecd1acc99957b14837f4cd747b9f26b3c02c.json new file mode 100644 index 000000000..bbe406e16 --- /dev/null +++ b/core/deposit/.sqlx/query-f3fc3e97653e968b7706ad72dbf9ecd1acc99957b14837f4cd747b9f26b3c02c.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO policies (id, process_type, committee_id, created_at) VALUES ($1, $2, $3, $4)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "f3fc3e97653e968b7706ad72dbf9ecd1acc99957b14837f4cd747b9f26b3c02c" +} diff --git a/core/deposit/.sqlx/query-f4215515cb8b8e4823a28867e118e7dc5877a809396cc1687fb287654dfbc126.json b/core/deposit/.sqlx/query-f4215515cb8b8e4823a28867e118e7dc5877a809396cc1687fb287654dfbc126.json new file mode 100644 index 000000000..75085b9d9 --- /dev/null +++ b/core/deposit/.sqlx/query-f4215515cb8b8e4823a28867e118e7dc5877a809396cc1687fb287654dfbc126.json @@ -0,0 +1,43 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT account_holder_id, created_at, id FROM deposit_accounts WHERE ((account_holder_id = $1) AND (COALESCE((created_at, id) > ($4, $3), $3 IS NULL))) ORDER BY created_at ASC, id ASC LIMIT $2) SELECT i.id AS \"entity_id: DepositAccountId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN deposit_account_events e ON i.id = e.id ORDER BY i.created_at asc, i.id asc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositAccountId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f4215515cb8b8e4823a28867e118e7dc5877a809396cc1687fb287654dfbc126" +} diff --git a/core/deposit/.sqlx/query-f7769c30ea3f8b0a4f96a3a033c9f28a94eaba9cccca0d51f6d19fe435967dbb.json b/core/deposit/.sqlx/query-f7769c30ea3f8b0a4f96a3a033c9f28a94eaba9cccca0d51f6d19fe435967dbb.json new file mode 100644 index 000000000..6c590f49e --- /dev/null +++ b/core/deposit/.sqlx/query-f7769c30ea3f8b0a4f96a3a033c9f28a94eaba9cccca0d51f6d19fe435967dbb.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_deposits WHERE reference = $1) SELECT i.id AS \"entity_id: DepositId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_deposit_events e ON i.id = e.id ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: DepositId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f7769c30ea3f8b0a4f96a3a033c9f28a94eaba9cccca0d51f6d19fe435967dbb" +} diff --git a/core/deposit/.sqlx/query-f7bac8b748ff6e5b70952d2ff5efe97a704b71707bcc506db2feb941b5e314f3.json b/core/deposit/.sqlx/query-f7bac8b748ff6e5b70952d2ff5efe97a704b71707bcc506db2feb941b5e314f3.json new file mode 100644 index 000000000..2560d1d99 --- /dev/null +++ b/core/deposit/.sqlx/query-f7bac8b748ff6e5b70952d2ff5efe97a704b71707bcc506db2feb941b5e314f3.json @@ -0,0 +1,41 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH entities AS (SELECT id FROM core_withdrawals WHERE (COALESCE(id < $2, true)) ORDER BY id DESC LIMIT $1) SELECT i.id AS \"entity_id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM entities i JOIN core_withdrawal_events e ON i.id = e.id ORDER BY i.id desc, i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "entity_id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f7bac8b748ff6e5b70952d2ff5efe97a704b71707bcc506db2feb941b5e314f3" +} diff --git a/core/deposit/.sqlx/query-f8bc7e13180dafd658190520f81f6cbce2cb9976ede2b5d1c2065f2cc47d27dc.json b/core/deposit/.sqlx/query-f8bc7e13180dafd658190520f81f6cbce2cb9976ede2b5d1c2065f2cc47d27dc.json new file mode 100644 index 000000000..caaf2edb7 --- /dev/null +++ b/core/deposit/.sqlx/query-f8bc7e13180dafd658190520f81f6cbce2cb9976ede2b5d1c2065f2cc47d27dc.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT i.id AS \"id: WithdrawalId\", e.sequence, e.event, e.recorded_at FROM core_withdrawals i JOIN core_withdrawal_events e ON i.id = e.id WHERE i.id = ANY($1) ORDER BY i.id, e.sequence", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id: WithdrawalId", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "sequence", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "event", + "type_info": "Jsonb" + }, + { + "ordinal": 3, + "name": "recorded_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f8bc7e13180dafd658190520f81f6cbce2cb9976ede2b5d1c2065f2cc47d27dc" +} diff --git a/core/deposit/.sqlx/query-fecae87d783c20d975d3f14748ca4c3b885a24f2af3c6e4170285551e2b6ac3c.json b/core/deposit/.sqlx/query-fecae87d783c20d975d3f14748ca4c3b885a24f2af3c6e4170285551e2b6ac3c.json new file mode 100644 index 000000000..fc9eb310f --- /dev/null +++ b/core/deposit/.sqlx/query-fecae87d783c20d975d3f14748ca4c3b885a24f2af3c6e4170285551e2b6ac3c.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE approval_processes SET process_type = $2, committee_id = $3, policy_id = $4 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "fecae87d783c20d975d3f14748ca4c3b885a24f2af3c6e4170285551e2b6ac3c" +} diff --git a/core/deposit/Cargo.toml b/core/deposit/Cargo.toml new file mode 100644 index 000000000..620d4f548 --- /dev/null +++ b/core/deposit/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "deposit" +version = "0.1.0" +edition = "2021" + +[features] + +default = ["governance"] +fail-on-warnings = [] +graphql = ["es-entity/graphql"] +governance = ["dep:governance"] + +[dependencies] +core-money = { path = "../money" } +governance = { path = "../governance", optional = true } + +audit = { path = "../../lib/audit" } +authz = { path = "../../lib/authz" } +outbox = { path = "../../lib/outbox" } + +cala-ledger = { workspace = true } +es-entity = { workspace = true } +sqlx = { workspace = true } + +strum = { workspace = true } +chrono = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +derive_builder = { workspace = true } +rust_decimal = { workspace = true } + +[dev-dependencies] +authz = { path = "../../lib/authz", features = ["test-dummy"] } + +tokio = { workspace = true } +anyhow = { workspace = true } +rust_decimal_macros = { workspace = true } diff --git a/core/deposit/src/account/entity.rs b/core/deposit/src/account/entity.rs new file mode 100644 index 000000000..f1c8fafd9 --- /dev/null +++ b/core/deposit/src/account/entity.rs @@ -0,0 +1,69 @@ +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +use es_entity::*; + +use audit::AuditInfo; + +use crate::primitives::*; + +#[derive(EsEvent, Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[es_event(id = "DepositAccountId")] +pub enum DepositAccountEvent { + Initialized { + id: DepositAccountId, + account_holder_id: DepositAccountHolderId, + ledger_account_id: LedgerAccountId, + audit_info: AuditInfo, + }, +} + +#[derive(EsEntity, Builder)] +#[builder(pattern = "owned", build_fn(error = "EsEntityError"))] +pub struct DepositAccount { + pub id: DepositAccountId, + pub(super) events: EntityEvents, +} + +impl TryFromEvents for DepositAccount { + fn try_from_events(events: EntityEvents) -> Result { + let mut builder = DepositAccountBuilder::default(); + for event in events.iter_all() { + match event { + DepositAccountEvent::Initialized { id, .. } => builder = builder.id(*id), + } + } + builder.events(events).build() + } +} + +#[derive(Debug, Builder)] +pub struct NewDepositAccount { + #[builder(setter(into))] + pub(super) id: DepositAccountId, + #[builder(setter(into))] + pub(super) account_holder_id: DepositAccountHolderId, + #[builder(setter(into))] + pub audit_info: AuditInfo, +} + +impl NewDepositAccount { + pub fn builder() -> NewDepositAccountBuilder { + NewDepositAccountBuilder::default() + } +} + +impl IntoEvents for NewDepositAccount { + fn into_events(self) -> EntityEvents { + EntityEvents::init( + self.id, + [DepositAccountEvent::Initialized { + id: self.id, + account_holder_id: self.account_holder_id, + ledger_account_id: self.id.into(), + audit_info: self.audit_info, + }], + ) + } +} diff --git a/core/deposit/src/account/error.rs b/core/deposit/src/account/error.rs new file mode 100644 index 000000000..f519b6e43 --- /dev/null +++ b/core/deposit/src/account/error.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum DepositAccountError { + #[error("CommitteeError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("CommitteeError - EsEntityError: {0}")] + EsEntityError(es_entity::EsEntityError), + #[error("CommitteeError - CursorDestructureError: {0}")] + CursorDestructureError(#[from] es_entity::CursorDestructureError), +} + +es_entity::from_es_entity_error!(DepositAccountError); diff --git a/core/deposit/src/account/mod.rs b/core/deposit/src/account/mod.rs new file mode 100644 index 000000000..14499942d --- /dev/null +++ b/core/deposit/src/account/mod.rs @@ -0,0 +1,6 @@ +mod entity; +pub mod error; +mod repo; + +pub(super) use entity::*; +pub(super) use repo::*; diff --git a/core/deposit/src/account/repo.rs b/core/deposit/src/account/repo.rs new file mode 100644 index 000000000..d20cc35b1 --- /dev/null +++ b/core/deposit/src/account/repo.rs @@ -0,0 +1,24 @@ +use sqlx::PgPool; + +use es_entity::*; + +use crate::primitives::{DepositAccountHolderId, DepositAccountId}; + +use super::{entity::*, error::*}; + +#[derive(EsRepo, Clone)] +#[es_repo( + entity = "DepositAccount", + err = "DepositAccountError", + columns(account_holder_id(ty = "DepositAccountHolderId", list_for, update(persist = false))) +)] +pub struct DepositAccountRepo { + #[allow(dead_code)] + pool: PgPool, +} + +impl DepositAccountRepo { + pub fn new(pool: &PgPool) -> Self { + Self { pool: pool.clone() } + } +} diff --git a/core/deposit/src/deposit/entity.rs b/core/deposit/src/deposit/entity.rs new file mode 100644 index 000000000..358e62db8 --- /dev/null +++ b/core/deposit/src/deposit/entity.rs @@ -0,0 +1,98 @@ +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +use es_entity::*; + +use audit::AuditInfo; + +use crate::primitives::{DepositAccountId, DepositId}; + +#[derive(EsEvent, Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[es_event(id = "DepositId")] +pub enum DepositEvent { + Initialized { + id: DepositId, + deposit_account_id: DepositAccountId, + reference: String, + audit_info: AuditInfo, + }, +} + +#[derive(EsEntity, Builder)] +#[builder(pattern = "owned", build_fn(error = "EsEntityError"))] +pub struct Deposit { + pub id: DepositId, + pub deposit_account_id: DepositAccountId, + pub reference: String, + pub(super) events: EntityEvents, +} + +impl Deposit { + pub fn created_at(&self) -> chrono::DateTime { + self.events + .entity_first_persisted_at() + .expect("No events for deposit") + } +} + +impl TryFromEvents for Deposit { + fn try_from_events(events: EntityEvents) -> Result { + let mut builder = DepositBuilder::default(); + for event in events.iter_all() { + match event { + DepositEvent::Initialized { + id, + reference, + deposit_account_id, + .. + } => { + builder = builder + .id(*id) + .deposit_account_id(*deposit_account_id) + .reference(reference.clone()); + } + } + } + builder.events(events).build() + } +} + +#[derive(Debug, Builder)] +pub struct NewDeposit { + #[builder(setter(into))] + pub(super) id: DepositId, + #[builder(setter(into))] + pub(super) deposit_account_id: DepositAccountId, + reference: Option, + #[builder(setter(into))] + pub audit_info: AuditInfo, +} + +impl NewDeposit { + pub fn builder() -> NewDepositBuilder { + NewDepositBuilder::default() + } + + pub(super) fn reference(&self) -> String { + match self.reference.as_deref() { + None => self.id.to_string(), + Some("") => self.id.to_string(), + Some(reference) => reference.to_string(), + } + } +} + +impl IntoEvents for NewDeposit { + fn into_events(self) -> EntityEvents { + EntityEvents::init( + self.id, + [DepositEvent::Initialized { + reference: self.reference(), + id: self.id, + deposit_account_id: self.deposit_account_id, + audit_info: self.audit_info, + }], + ) + } +} diff --git a/core/deposit/src/deposit/error.rs b/core/deposit/src/deposit/error.rs new file mode 100644 index 000000000..46a7c3127 --- /dev/null +++ b/core/deposit/src/deposit/error.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum DepositError { + #[error("DepositError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("DepositError - EsEntityError: {0}")] + EsEntityError(es_entity::EsEntityError), + #[error("DepositError - CursorDestructureError: {0}")] + CursorDestructureError(#[from] es_entity::CursorDestructureError), +} + +es_entity::from_es_entity_error!(DepositError); diff --git a/core/deposit/src/deposit/mod.rs b/core/deposit/src/deposit/mod.rs new file mode 100644 index 000000000..40a72af29 --- /dev/null +++ b/core/deposit/src/deposit/mod.rs @@ -0,0 +1,161 @@ +mod entity; +pub mod error; +mod repo; + +pub(super) use entity::*; +pub(super) use repo::*; +// use authz::PermissionCheck; + +// use crate::{ +// audit::AuditInfo, +// authorization::{Authorization, DepositAction, Object}, +// customer::Customers, +// data_export::Export, +// ledger::Ledger, +// primitives::{CustomerId, DepositId, Subject, UsdCents}, +// }; + +// pub use entity::*; +// use error::DepositError; +// pub use repo::{deposit_cursor::DepositsByCreatedAtCursor, DepositRepo}; + +// #[derive(Clone)] +// pub struct Deposits { +// repo: DepositRepo, +// customers: Customers, +// ledger: Ledger, +// authz: Authorization, +// } + +// impl Deposits { +// pub fn new( +// pool: &sqlx::PgPool, +// customers: &Customers, +// ledger: &Ledger, +// authz: &Authorization, +// export: &Export, +// ) -> Self { +// let repo = DepositRepo::new(pool, export); +// Self { +// repo, +// customers: customers.clone(), +// ledger: ledger.clone(), +// authz: authz.clone(), +// } +// } + +// pub fn repo(&self) -> &DepositRepo { +// &self.repo +// } + +// pub async fn subject_can_record( +// &self, +// sub: &Subject, +// enforce: bool, +// ) -> Result, DepositError> { +// Ok(self +// .authz +// .evaluate_permission(sub, Object::Deposit, DepositAction::Record, enforce) +// .await?) +// } + +// pub async fn record( +// &self, +// sub: &Subject, +// customer_id: impl Into, +// amount: UsdCents, +// reference: Option, +// ) -> Result { +// let audit_info = self +// .subject_can_record(sub, true) +// .await? +// .expect("audit info missing"); + +// let customer_id = customer_id.into(); +// let customer = self.customers.repo().find_by_id(customer_id).await?; +// let new_deposit = NewDeposit::builder() +// .id(DepositId::new()) +// .customer_id(customer_id) +// .amount(amount) +// .reference(reference.clone()) +// .credit_account_id(customer.account_ids.on_balance_sheet_deposit_account_id) +// .audit_info(audit_info) +// .build() +// .expect("Could not build Deposit"); + +// let mut db = self.repo.begin_op().await?; +// let deposit = self.repo.create_in_op(&mut db, new_deposit).await?; + +// self.ledger +// .record_deposit_for_customer( +// deposit.id, +// customer.account_ids, +// amount, +// deposit.reference.clone(), +// ) +// .await?; + +// db.commit().await?; + +// Ok(deposit) +// } + +// pub async fn find_by_id( +// &self, +// sub: &Subject, +// id: impl Into + std::fmt::Debug, +// ) -> Result, DepositError> { +// self.authz +// .enforce_permission(sub, Object::Deposit, DepositAction::Read) +// .await?; + +// match self.repo.find_by_id(id.into()).await { +// Ok(deposit) => Ok(Some(deposit)), +// Err(DepositError::CouldNotFindById(_)) => Ok(None), +// Err(e) => Err(e), +// } +// } + +// #[instrument(name = "deposit.list_for_customer", skip(self))] +// pub async fn list_for_customer( +// &self, +// sub: &Subject, +// customer_id: impl Into + std::fmt::Debug, +// ) -> Result, DepositError> { +// let customer_id = customer_id.into(); +// self.authz +// .enforce_permission(sub, Object::Deposit, DepositAction::List) +// .await?; + +// Ok(self +// .repo +// .list_for_customer_id_by_created_at( +// customer_id, +// Default::default(), +// es_entity::ListDirection::Descending, +// ) +// .await? +// .entities) +// } + +// pub async fn list( +// &self, +// sub: &Subject, +// query: es_entity::PaginatedQueryArgs, +// ) -> Result, DepositError> +// { +// self.authz +// .enforce_permission(sub, Object::Deposit, DepositAction::List) +// .await?; +// self.repo +// .list_by_created_at(query, es_entity::ListDirection::Descending) +// .await +// } + +// pub async fn find_all>( +// &self, +// ids: &[DepositId], +// ) -> Result, DepositError> { +// self.repo.find_all(ids).await +// } +// } diff --git a/core/deposit/src/deposit/repo.rs b/core/deposit/src/deposit/repo.rs new file mode 100644 index 000000000..c042d3fdb --- /dev/null +++ b/core/deposit/src/deposit/repo.rs @@ -0,0 +1,27 @@ +use sqlx::PgPool; + +use es_entity::*; + +use crate::primitives::{DepositAccountId, DepositId}; + +use super::{entity::*, error::*}; + +#[derive(EsRepo, Clone)] +#[es_repo( + entity = "Deposit", + err = "DepositError", + columns( + deposit_account_id(ty = "DepositAccountId", list_for, update(persist = false)), + reference(ty = "String", create(accessor = "reference()")) + ), + tbl_prefix = "core" +)] +pub struct DepositRepo { + pool: PgPool, +} + +impl DepositRepo { + pub fn new(pool: &PgPool) -> Self { + Self { pool: pool.clone() } + } +} diff --git a/core/deposit/src/error.rs b/core/deposit/src/error.rs new file mode 100644 index 000000000..cbbef24b5 --- /dev/null +++ b/core/deposit/src/error.rs @@ -0,0 +1,17 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum CoreDepositError { + #[error("CoreDepositError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("CoreDepositError - AuthorizationError: {0}")] + AuthorizationError(#[from] authz::error::AuthorizationError), + #[error("CoreDepositError - DepositAccountError: {0}")] + DepositAccountError(#[from] crate::account::error::DepositAccountError), + #[error("CoreDepositError - DepositError: {0}")] + DepositError(#[from] crate::deposit::error::DepositError), + #[error("CoreDepositError - WithdrawalError: {0}")] + WithdrawalError(#[from] crate::withdrawal::error::WithdrawalError), + #[error("CoreDepositError - DepositLedgerError: {0}")] + DepositLedgerError(#[from] crate::ledger::error::DepositLedgerError), +} diff --git a/core/deposit/src/event.rs b/core/deposit/src/event.rs new file mode 100644 index 000000000..4d3e2bfed --- /dev/null +++ b/core/deposit/src/event.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum CoreDepositEvent { + DepositAccountCreated, +} diff --git a/core/deposit/src/ledger/error.rs b/core/deposit/src/ledger/error.rs new file mode 100644 index 000000000..fbfd3dd89 --- /dev/null +++ b/core/deposit/src/ledger/error.rs @@ -0,0 +1,17 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum DepositLedgerError { + #[error("DepositLedgerError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("DepositLedgerError - CalaLedger: {0}")] + CalaLedger(#[from] cala_ledger::error::LedgerError), + #[error("DepositLedgerError - CalaAccountError: {0}")] + CalaAccount(#[from] cala_ledger::account::error::AccountError), + #[error("DepositLedgerError - CalaTxTemplateError: {0}")] + CalaTxTemplate(#[from] cala_ledger::tx_template::error::TxTemplateError), + #[error("DepositLedgerError - CalaBalanceError: {0}")] + CalaBalance(#[from] cala_ledger::balance::error::BalanceError), + #[error("DepositLedgerError - ConversionError: {0}")] + ConversionError(#[from] core_money::ConversionError), +} diff --git a/core/deposit/src/ledger/mod.rs b/core/deposit/src/ledger/mod.rs new file mode 100644 index 000000000..48794fad7 --- /dev/null +++ b/core/deposit/src/ledger/mod.rs @@ -0,0 +1,181 @@ +pub mod error; +mod templates; + +use cala_ledger::{ + account::{error::AccountError, *}, + CalaLedger, Currency, DebitOrCredit, JournalId, TransactionId, +}; +use templates::CONFIRM_WITHDRAW_CODE; + +use crate::primitives::UsdCents; + +use error::*; + +#[derive(Clone)] +pub struct DepositLedger { + cala: CalaLedger, + journal_id: JournalId, + deposit_omnibus_account_id: AccountId, + usd: Currency, +} + +impl DepositLedger { + pub async fn init( + cala: &CalaLedger, + journal_id: JournalId, + omnibus_account_code: String, + ) -> Result { + let deposit_omnibus_account_id = + Self::create_deposit_omnibus_account(cala, omnibus_account_code.clone()).await?; + + templates::RecordDeposit::init(cala).await?; + templates::InitiateWithdraw::init(cala).await?; + templates::CancelWithdraw::init(cala).await?; + templates::ConfirmWithdraw::init(cala).await?; + + Ok(Self { + cala: cala.clone(), + journal_id, + deposit_omnibus_account_id, + usd: "USD".parse().expect("Could not parse 'USD'"), + }) + } + + pub async fn create_account_for_deposit_account( + &self, + op: es_entity::DbOp<'_>, + id: impl Into, + code: String, + ) -> Result<(), DepositLedgerError> { + let mut op = self.cala.ledger_operation_from_db_op(op); + + let new_account = NewAccount::builder() + .id(id) + .name("Deposit Account") + .code(code) + .build() + .expect("Could not build new account"); + + self.cala + .accounts() + .create_in_op(&mut op, new_account) + .await?; + + op.commit().await?; + + Ok(()) + } + + pub async fn record_deposit( + &self, + op: es_entity::DbOp<'_>, + tx_id: impl Into, + amount: UsdCents, + credit_account_id: impl Into, + ) -> Result<(), DepositLedgerError> { + let tx_id = tx_id.into(); + let mut op = self.cala.ledger_operation_from_db_op(op); + + let params = templates::RecordDepositParams { + journal_id: self.journal_id, + currency: self.usd, + amount: amount.to_usd(), + deposit_omnibus_account_id: self.deposit_omnibus_account_id, + credit_account_id: credit_account_id.into(), + }; + self.cala + .post_transaction_in_op(&mut op, tx_id, templates::RECORD_DEPOSIT_CODE, params) + .await?; + + op.commit().await?; + Ok(()) + } + + pub async fn initiate_withdrawal( + &self, + op: es_entity::DbOp<'_>, + tx_id: impl Into, + amount: UsdCents, + credit_account_id: impl Into, + ) -> Result<(), DepositLedgerError> { + let tx_id = tx_id.into(); + let mut op = self.cala.ledger_operation_from_db_op(op); + let params = templates::InitiateWithdrawParams { + journal_id: self.journal_id, + currency: self.usd, + amount: amount.to_usd(), + deposit_omnibus_account_id: self.deposit_omnibus_account_id, + credit_account_id: credit_account_id.into(), + }; + + self.cala + .post_transaction_in_op(&mut op, tx_id, templates::INITIATE_WITHDRAW_CODE, params) + .await?; + + op.commit().await?; + Ok(()) + } + + pub async fn confirm_withdrawal( + &self, + op: es_entity::DbOp<'_>, + tx_id: impl Into, + correlation_id: impl Into, + credit_account_id: impl Into, + amount: UsdCents, + external_id: String, + ) -> Result<(), DepositLedgerError> { + let tx_id = tx_id.into(); + let mut op = self.cala.ledger_operation_from_db_op(op); + let params = templates::ConfirmWithdrawParams { + journal_id: self.journal_id, + currency: self.usd, + amount: amount.to_usd(), + deposit_omnibus_account_id: self.deposit_omnibus_account_id, + credit_account_id: credit_account_id.into(), + correlation_id: correlation_id.into(), + external_id, + }; + + self.cala + .post_transaction_in_op(&mut op, tx_id, CONFIRM_WITHDRAW_CODE, params) + .await?; + op.commit().await?; + Ok(()) + } + + async fn create_deposit_omnibus_account( + cala: &CalaLedger, + code: String, + ) -> Result { + let new_account = NewAccount::builder() + .code(&code) + .id(AccountId::new()) + .name("Deposit Omnibus Account") + .description("Omnibus Account for Deposit module") + .normal_balance_type(DebitOrCredit::Debit) + .build() + .expect("Couldn't create onchain incoming account"); + match cala.accounts().create(new_account).await { + Err(AccountError::CodeAlreadyExists) => { + let account = cala.accounts().find_by_code(code).await?; + Ok(account.id) + } + Err(e) => Err(e.into()), + Ok(account) => Ok(account.id), + } + } + + pub async fn balance( + &self, + account_id: impl Into, + ) -> Result { + let balances = self + .cala + .balances() + .find(self.journal_id, account_id.into(), self.usd) + .await?; + + Ok(UsdCents::try_from_usd(balances.settled())?) + } +} diff --git a/core/deposit/src/ledger/templates/cancel_withdraw.rs b/core/deposit/src/ledger/templates/cancel_withdraw.rs new file mode 100644 index 000000000..84fb477ea --- /dev/null +++ b/core/deposit/src/ledger/templates/cancel_withdraw.rs @@ -0,0 +1,147 @@ +use rust_decimal::Decimal; +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::ledger::error::*; + +pub const CANCEL_WITHDRAW_CODE: &str = "CANCEL_WITHDRAW_CODE"; + +#[derive(Debug)] +pub struct CancelWithdrawParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, +} + +impl CancelWithdrawParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("deposit_omnibus_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("credit_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + CancelWithdrawParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + credit_account_id, + }: CancelWithdrawParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct CancelWithdraw; + +impl CancelWithdraw { + #[instrument(name = "ledger.cancel_withdraw.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), DepositLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Cancel a Withdraw'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + // check in graphql/cancel-withdraw the entry type + NewTxTemplateEntry::builder() + .entry_type("'CANCEL_WITHDRAW_PENDING_CR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("CREDIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'CANCEL_WITHDRAW_PENDING_DR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("DEBIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'CANCEL_WITHDRAW_SETTLED_DR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("DEBIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'CANCEL_WITHDRAW_SETTLED_CR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("CREDIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = CancelWithdrawParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(CANCEL_WITHDRAW_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/core/deposit/src/ledger/templates/confirm_withdraw.rs b/core/deposit/src/ledger/templates/confirm_withdraw.rs new file mode 100644 index 000000000..37200f9f3 --- /dev/null +++ b/core/deposit/src/ledger/templates/confirm_withdraw.rs @@ -0,0 +1,146 @@ +use rust_decimal::Decimal; + +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::ledger::error::*; + +pub const CONFIRM_WITHDRAW_CODE: &str = "CONFIRM_WITHDRAW_CODE"; + +#[derive(Debug)] +pub struct ConfirmWithdrawParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, + pub correlation_id: String, + pub external_id: String, +} + +impl ConfirmWithdrawParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("deposit_omnibus_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("credit_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("correlation_id") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("external_id") + .r#type(ParamDataType::String) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + ConfirmWithdrawParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + correlation_id, + external_id, + credit_account_id, + }: ConfirmWithdrawParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("correlation_id", correlation_id); + params.insert("external_id", external_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct ConfirmWithdraw; + +impl ConfirmWithdraw { + #[instrument(name = "ledger.confirm_withdraw.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), DepositLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Confirm a withdraw'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + // check in graphql/cancel-withdraw the entry type + NewTxTemplateEntry::builder() + .entry_type("'CONFIRM_WITHDRAW_PENDING_CR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("CREDIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'CONFIRM_WITHDRAW_PENDING_DR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("DEBIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = ConfirmWithdrawParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(CONFIRM_WITHDRAW_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/core/deposit/src/ledger/templates/initiate_withdraw.rs b/core/deposit/src/ledger/templates/initiate_withdraw.rs new file mode 100644 index 000000000..2e3b58dbf --- /dev/null +++ b/core/deposit/src/ledger/templates/initiate_withdraw.rs @@ -0,0 +1,146 @@ +use rust_decimal::Decimal; +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::ledger::error::*; + +pub const INITIATE_WITHDRAW_CODE: &str = "INITIATE_WITHDRAW_CODE"; + +#[derive(Debug)] +pub struct InitiateWithdrawParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, +} + +impl InitiateWithdrawParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("deposit_omnibus_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("credit_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + InitiateWithdrawParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + credit_account_id, + }: InitiateWithdrawParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct InitiateWithdraw; + +impl InitiateWithdraw { + #[instrument(name = "ledger.initiate_withdraw.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), DepositLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Initiate a withdraw'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + NewTxTemplateEntry::builder() + .entry_type("'INITIATE_WITHDRAW_SETTLED_DR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("CREDIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'INITIATE_WITHDRAW_SETTLED_CR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("DEBIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'INITIATE_WITHDRAW_PENDING_DR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("DEBIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'INITIATE_WITHDRAW_PENDING_CR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("CREDIT") + .layer("PENDING") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = InitiateWithdrawParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(INITIATE_WITHDRAW_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/core/deposit/src/ledger/templates/mod.rs b/core/deposit/src/ledger/templates/mod.rs new file mode 100644 index 000000000..2fffe54ec --- /dev/null +++ b/core/deposit/src/ledger/templates/mod.rs @@ -0,0 +1,9 @@ +mod cancel_withdraw; +mod confirm_withdraw; +mod initiate_withdraw; +mod record_deposit; + +pub use cancel_withdraw::*; +pub use confirm_withdraw::*; +pub use initiate_withdraw::*; +pub use record_deposit::*; diff --git a/core/deposit/src/ledger/templates/record_deposit.rs b/core/deposit/src/ledger/templates/record_deposit.rs new file mode 100644 index 000000000..4f2bb11f6 --- /dev/null +++ b/core/deposit/src/ledger/templates/record_deposit.rs @@ -0,0 +1,128 @@ +use rust_decimal::Decimal; +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::ledger::error::*; + +pub const RECORD_DEPOSIT_CODE: &str = "RECORD_DEPOSIT"; + +#[derive(Debug)] +pub struct RecordDepositParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, +} + +impl RecordDepositParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("deposit_omnibus_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("credit_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + RecordDepositParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + credit_account_id, + }: RecordDepositParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct RecordDeposit; + +impl RecordDeposit { + #[instrument(name = "ledger.record_deposit.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), DepositLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Record a deposit'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + NewTxTemplateEntry::builder() + .entry_type("'RECORD_DEPOSIT_DR'") + .currency("params.currency") + .account_id("params.deposit_omnibus_account_id") + .direction("DEBIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'RECORD_DEPOSIT_CR'") + .currency("params.currency") + .account_id("params.credit_account_id") + .direction("CREDIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = RecordDepositParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(RECORD_DEPOSIT_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/core/deposit/src/lib.rs b/core/deposit/src/lib.rs new file mode 100644 index 000000000..d2491418f --- /dev/null +++ b/core/deposit/src/lib.rs @@ -0,0 +1,240 @@ +#![cfg_attr(feature = "fail-on-warnings", deny(warnings))] +#![cfg_attr(feature = "fail-on-warnings", deny(clippy::all))] + +mod account; +mod deposit; +pub mod error; +mod event; +mod ledger; +mod primitives; +mod withdrawal; + +use tracing::instrument; + +use audit::AuditSvc; +use authz::PermissionCheck; +use cala_ledger::CalaLedger; +use outbox::{Outbox, OutboxEventMarker}; + +use account::*; +use deposit::*; +use error::*; +pub use event::*; +use ledger::*; +pub use primitives::*; +use withdrawal::*; + +pub struct CoreDeposit +where + Perms: PermissionCheck, + E: OutboxEventMarker, +{ + accounts: DepositAccountRepo, + deposits: DepositRepo, + withdrawals: WithdrawalRepo, + ledger: DepositLedger, + authz: Perms, + outbox: Outbox, +} + +impl Clone for CoreDeposit +where + Perms: PermissionCheck, + E: OutboxEventMarker, +{ + fn clone(&self) -> Self { + Self { + accounts: self.accounts.clone(), + deposits: self.deposits.clone(), + withdrawals: self.withdrawals.clone(), + ledger: self.ledger.clone(), + authz: self.authz.clone(), + outbox: self.outbox.clone(), + } + } +} + +impl CoreDeposit +where + Perms: PermissionCheck, + <::Audit as AuditSvc>::Action: From, + <::Audit as AuditSvc>::Object: From, + E: OutboxEventMarker, +{ + pub async fn init( + pool: &sqlx::PgPool, + authz: &Perms, + outbox: &Outbox, + cala: &CalaLedger, + journal_id: LedgerJournalId, + omnibus_account_code: String, + ) -> Result { + let accounts = DepositAccountRepo::new(pool); + let deposits = DepositRepo::new(pool); + let withdrawals = WithdrawalRepo::new(pool); + let ledger = DepositLedger::init(cala, journal_id, omnibus_account_code).await?; + let res = Self { + accounts, + deposits, + withdrawals, + authz: authz.clone(), + outbox: outbox.clone(), + ledger, + }; + Ok(res) + } + + #[instrument(name = "deposit.create_account", skip(self))] + pub async fn create_account( + &self, + sub: &<::Audit as AuditSvc>::Subject, + holder_id: impl Into + std::fmt::Debug, + ) -> Result { + let audit_info = self + .authz + .enforce_permission( + sub, + CoreDepositObject::all_deposit_accounts(), + CoreDepositAction::DEPOSIT_ACCOUNT_CREATE, + ) + .await?; + + let account_id = DepositAccountId::new(); + let new_account = NewDepositAccount::builder() + .id(account_id) + .account_holder_id(holder_id) + .audit_info(audit_info) + .build() + .expect("Could not build new committee"); + + let mut op = self.accounts.begin_op().await?; + let account = self.accounts.create_in_op(&mut op, new_account).await?; + self.ledger + .create_account_for_deposit_account(op, account_id, account_id.to_string()) + .await?; + Ok(account) + } + + #[instrument(name = "deposit.record_deposit", skip(self))] + pub async fn record_deposit( + &self, + sub: &<::Audit as AuditSvc>::Subject, + deposit_account_id: DepositAccountId, + amount: UsdCents, + reference: Option, + ) -> Result { + let audit_info = self + .authz + .enforce_permission( + sub, + CoreDepositObject::all_deposits(), + CoreDepositAction::DEPOSIT_CREATE, + ) + .await?; + + let deposit_id = DepositId::new(); + let new_deposit = NewDeposit::builder() + .id(deposit_id) + .deposit_account_id(deposit_account_id) + .reference(reference) + .audit_info(audit_info) + .build() + .expect("Could not build new committee"); + + let mut op = self.deposits.begin_op().await?; + let deposit = self.deposits.create_in_op(&mut op, new_deposit).await?; + self.ledger + .record_deposit(op, deposit_id, amount, deposit_account_id) + .await?; + Ok(deposit) + } + + pub async fn initiate_withdrawal( + &self, + sub: &<::Audit as AuditSvc>::Subject, + deposit_account_id: DepositAccountId, + amount: UsdCents, + reference: Option, + ) -> Result { + let audit_info = self + .authz + .enforce_permission( + sub, + CoreDepositObject::all_withdrawals(), + CoreDepositAction::WITHDRAWAL_INITIATE, + ) + .await?; + let withdrawal_id = WithdrawalId::new(); + let new_withdrawal = NewWithdrawal::builder() + .id(withdrawal_id) + .deposit_account_id(deposit_account_id) + .reference(reference) + .audit_info(audit_info) + .build() + .expect("Could not build new withdrawal"); + let mut op = self.withdrawals.begin_op().await?; + let withdrawal = self + .withdrawals + .create_in_op(&mut op, new_withdrawal) + .await?; + + // TODO: add approval process and check for balance + self.ledger + .initiate_withdrawal(op, withdrawal_id, amount, deposit_account_id) + .await?; + Ok(withdrawal) + } + + pub async fn confirm_withdrawal( + &self, + sub: &<::Audit as AuditSvc>::Subject, + withdrawal_id: impl Into, + ) -> Result { + let audit_info = self + .authz + .enforce_permission( + sub, + CoreDepositObject::all_withdrawals(), + CoreDepositAction::WITHDRAWAL_INITIATE, + ) + .await?; + let id = withdrawal_id.into(); + let mut withdrawal = self.withdrawals.find_by_id(id).await?; + let mut op = self.withdrawals.begin_op().await?; + let tx_id = withdrawal.confirm(audit_info)?; + self.withdrawals + .update_in_op(&mut op, &mut withdrawal) + .await?; + + self.ledger + .confirm_withdrawal( + op, + tx_id, + withdrawal.id.to_string(), + withdrawal.deposit_account_id, + UsdCents::ZERO, // TODO: use entries from initiate_withdraw to get this + format!("lana:withdraw:{}:confirm", withdrawal.id), + ) + .await?; + + Ok(withdrawal) + } + + pub async fn balance( + &self, + sub: &<::Audit as AuditSvc>::Subject, + account_id: DepositAccountId, + ) -> Result { + let _ = self + .authz + .enforce_permission( + sub, + CoreDepositObject::deposit_account(account_id), + CoreDepositAction::DEPOSIT_ACCOUNT_READ_BALANCE, + ) + .await?; + + let balance = self.ledger.balance(account_id).await?; + Ok(balance) + } +} diff --git a/core/deposit/src/main.rs b/core/deposit/src/main.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/core/deposit/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/core/deposit/src/primitives.rs b/core/deposit/src/primitives.rs new file mode 100644 index 000000000..c729b6634 --- /dev/null +++ b/core/deposit/src/primitives.rs @@ -0,0 +1,182 @@ +use std::{fmt::Display, str::FromStr}; + +use authz::AllOrOne; + +#[cfg(feature = "governance")] +pub use governance::ApprovalProcessId; + +pub use cala_ledger::primitives::{ + AccountId as LedgerAccountId, JournalId as LedgerJournalId, + TransactionId as LedgerTransactionId, +}; + +es_entity::entity_id! { + DepositAccountHolderId, + DepositAccountId, + WithdrawalId, + DepositId; + + DepositAccountId => LedgerAccountId, + DepositId => LedgerTransactionId, + WithdrawalId => LedgerTransactionId + +} + +pub use core_money::UsdCents; + +pub type DepositAccountAllOrOne = AllOrOne; +pub type DepositAllOrOne = AllOrOne; +pub type WithdrawalAllOrOne = AllOrOne; + +#[derive(Clone, Copy, Debug, PartialEq, strum::EnumDiscriminants)] +#[strum_discriminants(derive(strum::Display, strum::EnumString))] +#[strum_discriminants(strum(serialize_all = "kebab-case"))] +pub enum CoreDepositObject { + DepositAccount(DepositAccountAllOrOne), + Deposit(DepositAllOrOne), + Withdrawal(WithdrawalAllOrOne), +} + +impl CoreDepositObject { + pub fn all_deposit_accounts() -> Self { + CoreDepositObject::DepositAccount(AllOrOne::All) + } + + pub fn deposit_account(id: DepositAccountId) -> Self { + CoreDepositObject::DepositAccount(AllOrOne::ById(id)) + } + + pub fn all_deposits() -> Self { + CoreDepositObject::Deposit(AllOrOne::All) + } + + pub fn all_withdrawals() -> Self { + CoreDepositObject::Withdrawal(AllOrOne::All) + } +} + +impl Display for CoreDepositObject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let discriminant = CoreDepositObjectDiscriminants::from(self); + use CoreDepositObject::*; + match self { + DepositAccount(obj_ref) => write!(f, "{}/{}", discriminant, obj_ref), + Deposit(obj_ref) => write!(f, "{}/{}", discriminant, obj_ref), + Withdrawal(obj_ref) => write!(f, "{}/{}", discriminant, obj_ref), + } + } +} + +impl FromStr for CoreDepositObject { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let (entity, id) = s.split_once('/').expect("missing slash"); + use CoreDepositObjectDiscriminants::*; + let res = match entity.parse().expect("invalid entity") { + DepositAccount => { + let obj_ref = id + .parse() + .map_err(|_| "could not parse CoreDepositObject")?; + CoreDepositObject::DepositAccount(obj_ref) + } + Deposit => { + let obj_ref = id + .parse() + .map_err(|_| "could not parse CoreDepositObject")?; + CoreDepositObject::Deposit(obj_ref) + } + Withdrawal => { + let obj_ref = id + .parse() + .map_err(|_| "could not parse CoreDepositObject")?; + CoreDepositObject::Withdrawal(obj_ref) + } + }; + Ok(res) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, strum::EnumDiscriminants)] +#[strum_discriminants(derive(strum::Display, strum::EnumString))] +#[strum_discriminants(strum(serialize_all = "kebab-case"))] +pub enum CoreDepositAction { + DepositAccount(DepositAccountAction), + Deposit(DepositAction), + Withdrawal(WithdrawalAction), +} + +impl CoreDepositAction { + pub const DEPOSIT_ACCOUNT_CREATE: Self = + CoreDepositAction::DepositAccount(DepositAccountAction::Create); + + pub const DEPOSIT_ACCOUNT_READ_BALANCE: Self = + CoreDepositAction::DepositAccount(DepositAccountAction::ReadBalance); + + pub const DEPOSIT_CREATE: Self = CoreDepositAction::Deposit(DepositAction::Create); + pub const WITHDRAWAL_INITIATE: Self = CoreDepositAction::Withdrawal(WithdrawalAction::Initiate); +} + +impl Display for CoreDepositAction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:", CoreDepositActionDiscriminants::from(self))?; + use CoreDepositAction::*; + match self { + DepositAccount(action) => action.fmt(f), + Deposit(action) => action.fmt(f), + Withdrawal(action) => action.fmt(f), + } + } +} + +impl FromStr for CoreDepositAction { + type Err = strum::ParseError; + + fn from_str(s: &str) -> Result { + let (entity, action) = s.split_once(':').expect("missing colon"); + use CoreDepositActionDiscriminants::*; + let res = match entity.parse()? { + DepositAccount => CoreDepositAction::from(action.parse::()?), + Deposit => CoreDepositAction::from(action.parse::()?), + Withdrawal => CoreDepositAction::from(action.parse::()?), + }; + Ok(res) + } +} + +#[derive(PartialEq, Clone, Copy, Debug, strum::Display, strum::EnumString)] +#[strum(serialize_all = "kebab-case")] +pub enum DepositAccountAction { + Create, + ReadBalance, +} + +impl From for CoreDepositAction { + fn from(action: DepositAccountAction) -> Self { + CoreDepositAction::DepositAccount(action) + } +} + +#[derive(PartialEq, Clone, Copy, Debug, strum::Display, strum::EnumString)] +#[strum(serialize_all = "kebab-case")] +pub enum DepositAction { + Create, +} + +impl From for CoreDepositAction { + fn from(action: DepositAction) -> Self { + CoreDepositAction::Deposit(action) + } +} + +#[derive(PartialEq, Clone, Copy, Debug, strum::Display, strum::EnumString)] +#[strum(serialize_all = "kebab-case")] +pub enum WithdrawalAction { + Initiate, +} + +impl From for CoreDepositAction { + fn from(action: WithdrawalAction) -> Self { + CoreDepositAction::Withdrawal(action) + } +} diff --git a/core/deposit/src/withdrawal/entity.rs b/core/deposit/src/withdrawal/entity.rs new file mode 100644 index 000000000..0432a93bf --- /dev/null +++ b/core/deposit/src/withdrawal/entity.rs @@ -0,0 +1,187 @@ +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +use es_entity::*; + +#[cfg(feature = "governance")] +use crate::primitives::ApprovalProcessId; +use crate::primitives::{DepositAccountId, LedgerTransactionId, WithdrawalId}; +use audit::AuditInfo; + +use super::error::WithdrawalError; + +#[derive(EsEvent, Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[es_event(id = "WithdrawalId")] +pub enum WithdrawalEvent { + Initialized { + id: WithdrawalId, + deposit_account_id: DepositAccountId, + reference: String, + audit_info: AuditInfo, + }, + #[cfg(feature = "governance")] + ApprovalProcessStarted { + approval_process_id: ApprovalProcessId, + audit_info: AuditInfo, + }, + #[cfg(feature = "governance")] + ApprovalProcessConcluded { + approval_process_id: ApprovalProcessId, + approved: bool, + audit_info: AuditInfo, + }, + Confirmed { + ledger_tx_id: LedgerTransactionId, + audit_info: AuditInfo, + }, + Cancelled { + ledger_tx_id: LedgerTransactionId, + audit_info: AuditInfo, + }, +} + +#[derive(EsEntity, Builder)] +#[builder(pattern = "owned", build_fn(error = "EsEntityError"))] +pub struct Withdrawal { + pub id: WithdrawalId, + pub deposit_account_id: DepositAccountId, + pub reference: String, + #[cfg(feature = "governance")] + pub approval_process_id: ApprovalProcessId, + pub(super) events: EntityEvents, +} + +impl Withdrawal { + pub fn created_at(&self) -> chrono::DateTime { + self.events + .entity_first_persisted_at() + .expect("No events for deposit") + } + + pub fn confirm( + &mut self, + audit_info: AuditInfo, + ) -> Result { + match self.is_approved_or_denied() { + Some(false) => return Err(WithdrawalError::NotApproved(self.id)), + None => return Err(WithdrawalError::NotApproved(self.id)), + _ => (), + } + + if self.is_confirmed() { + return Err(WithdrawalError::AlreadyConfirmed(self.id)); + } + + if self.is_cancelled() { + return Err(WithdrawalError::AlreadyCancelled(self.id)); + } + + let ledger_tx_id = LedgerTransactionId::new(); + self.events.push(WithdrawalEvent::Confirmed { + ledger_tx_id, + audit_info, + }); + + Ok(ledger_tx_id) + } + + fn is_confirmed(&self) -> bool { + self.events + .iter_all() + .any(|e| matches!(e, WithdrawalEvent::Confirmed { .. })) + } + + pub(super) fn is_approved_or_denied(&self) -> Option { + self.events.iter_all().find_map(|e| { + if let WithdrawalEvent::ApprovalProcessConcluded { approved, .. } = e { + Some(*approved) + } else { + None + } + }) + } + + fn is_cancelled(&self) -> bool { + self.events + .iter_all() + .any(|e| matches!(e, WithdrawalEvent::Cancelled { .. })) + } +} + +impl TryFromEvents for Withdrawal { + fn try_from_events(events: EntityEvents) -> Result { + let mut builder = WithdrawalBuilder::default(); + for event in events.iter_all() { + match event { + WithdrawalEvent::Initialized { + id, + reference, + deposit_account_id, + .. + } => { + builder = builder + .id(*id) + .deposit_account_id(*deposit_account_id) + .reference(reference.clone()); + } + #[cfg(feature = "governance")] + WithdrawalEvent::ApprovalProcessStarted { + approval_process_id, + .. + } => builder = builder.approval_process_id(*approval_process_id), + _ => {} + } + } + builder.events(events).build() + } +} + +#[derive(Debug, Builder)] +pub struct NewWithdrawal { + #[builder(setter(into))] + pub(super) id: WithdrawalId, + #[builder(setter(into))] + pub(super) deposit_account_id: DepositAccountId, + #[cfg(feature = "governance")] + #[builder(setter(into))] + pub(super) approval_process_id: ApprovalProcessId, + reference: Option, + #[builder(setter(into))] + pub audit_info: AuditInfo, +} + +impl NewWithdrawal { + pub fn builder() -> NewWithdrawalBuilder { + NewWithdrawalBuilder::default() + } + + pub(super) fn reference(&self) -> String { + match self.reference.as_deref() { + None => self.id.to_string(), + Some("") => self.id.to_string(), + Some(reference) => reference.to_string(), + } + } +} + +impl IntoEvents for NewWithdrawal { + fn into_events(self) -> EntityEvents { + EntityEvents::init( + self.id, + [ + WithdrawalEvent::Initialized { + reference: self.reference(), + id: self.id, + deposit_account_id: self.deposit_account_id, + audit_info: self.audit_info.clone(), + }, + #[cfg(feature = "governance")] + WithdrawalEvent::ApprovalProcessStarted { + approval_process_id: self.approval_process_id, + audit_info: self.audit_info, + }, + ], + ) + } +} diff --git a/core/deposit/src/withdrawal/error.rs b/core/deposit/src/withdrawal/error.rs new file mode 100644 index 000000000..81e7a7103 --- /dev/null +++ b/core/deposit/src/withdrawal/error.rs @@ -0,0 +1,21 @@ +use thiserror::Error; + +use crate::primitives::WithdrawalId; + +#[derive(Error, Debug)] +pub enum WithdrawalError { + #[error("WithdrawalError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("WithdrawalError - EsEntityError: {0}")] + EsEntityError(es_entity::EsEntityError), + #[error("WithdrawalError - CursorDestructureError: {0}")] + CursorDestructureError(#[from] es_entity::CursorDestructureError), + #[error("WithdrawalError - AlreadyConfirmed: {0}")] + AlreadyConfirmed(WithdrawalId), + #[error("WithdrawalError - AlreadyCancelled: {0}")] + AlreadyCancelled(WithdrawalId), + #[error("WithdrawalError - NotApproved: {0}")] + NotApproved(WithdrawalId), +} + +es_entity::from_es_entity_error!(WithdrawalError); diff --git a/core/deposit/src/withdrawal/mod.rs b/core/deposit/src/withdrawal/mod.rs new file mode 100644 index 000000000..14499942d --- /dev/null +++ b/core/deposit/src/withdrawal/mod.rs @@ -0,0 +1,6 @@ +mod entity; +pub mod error; +mod repo; + +pub(super) use entity::*; +pub(super) use repo::*; diff --git a/core/deposit/src/withdrawal/repo.rs b/core/deposit/src/withdrawal/repo.rs new file mode 100644 index 000000000..eef194bd6 --- /dev/null +++ b/core/deposit/src/withdrawal/repo.rs @@ -0,0 +1,28 @@ +use sqlx::PgPool; + +use es_entity::*; + +use crate::primitives::{ApprovalProcessId, DepositAccountId, WithdrawalId}; + +use super::{entity::*, error::*}; + +#[derive(EsRepo, Clone)] +#[es_repo( + entity = "Withdrawal", + err = "WithdrawalError", + columns( + deposit_account_id(ty = "DepositAccountId", list_for, update(persist = false)), + approval_process_id(ty = "ApprovalProcessId", update(persist = false)), + reference(ty = "String", create(accessor = "reference()")) + ), + tbl_prefix = "core" +)] +pub struct WithdrawalRepo { + pool: PgPool, +} + +impl WithdrawalRepo { + pub fn new(pool: &PgPool) -> Self { + Self { pool: pool.clone() } + } +} diff --git a/core/deposit/tests/deposit.rs b/core/deposit/tests/deposit.rs new file mode 100644 index 000000000..ee3fc793d --- /dev/null +++ b/core/deposit/tests/deposit.rs @@ -0,0 +1,63 @@ +use rust_decimal_macros::dec; + +use authz::dummy::DummySubject; +use cala_ledger::{CalaLedger, CalaLedgerConfig}; +use deposit::*; + +pub async fn init_pool() -> anyhow::Result { + let pg_host = std::env::var("PG_HOST").unwrap_or("localhost".to_string()); + let pg_con = format!("postgres://user:password@{pg_host}:5433/pg"); + let pool = sqlx::PgPool::connect(&pg_con).await?; + Ok(pool) +} + +pub async fn init_journal(cala: &CalaLedger) -> anyhow::Result { + use cala_ledger::journal::*; + + let id = JournalId::new(); + let new = NewJournal::builder() + .id(id) + .name("Test journal") + .build() + .unwrap(); + let journal = cala.journals().create(new).await?; + Ok(journal.id) +} + +#[tokio::test] +async fn deposit() -> anyhow::Result<()> { + let pool = init_pool().await?; + + let outbox = outbox::Outbox::::init(&pool).await?; + let authz = authz::dummy::DummyPerms::::new(); + + let cala_config = CalaLedgerConfig::builder() + .pool(pool.clone()) + .exec_migrations(false) + .build()?; + let cala = CalaLedger::init(cala_config).await?; + + let journal_id = init_journal(&cala).await?; + let omnibus_code = journal_id.to_string(); + + let deposit = + CoreDeposit::init(&pool, &authz, &outbox, &cala, journal_id, omnibus_code).await?; + + let account_holder_id = DepositAccountHolderId::new(); + let account = deposit + .create_account(&DummySubject, account_holder_id) + .await?; + deposit + .record_deposit( + &DummySubject, + account.id, + UsdCents::try_from_usd(dec!(1000000)).unwrap(), + None, + ) + .await?; + let balance = deposit.balance(&DummySubject, account.id).await?; + + // return zero when no deposit + assert_eq!(balance, UsdCents::try_from_usd(dec!(1000000)).unwrap()); + Ok(()) +} diff --git a/core/governance/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json b/core/governance/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json deleted file mode 100644 index eb3a84f04..000000000 --- a/core/governance/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )\n VALUES ( $1, $2, $3, $4, $5, $6, $7 )", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164" -} diff --git a/core/governance/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json b/core/governance/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json deleted file mode 100644 index 1ea12e396..000000000 --- a/core/governance/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v3 is NULL OR v3 = COALESCE($2,v3)) AND\n (v4 is NULL OR v4 = COALESCE($3,v4)) AND\n (v5 is NULL OR v5 = COALESCE($4,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0" -} diff --git a/core/governance/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json b/core/governance/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json deleted file mode 100644 index 8046c5db1..000000000 --- a/core/governance/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9" -} diff --git a/core/governance/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json b/core/governance/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json deleted file mode 100644 index e246e53b4..000000000 --- a/core/governance/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n v0 = $2 AND\n v1 = $3 AND\n v2 = $4 AND\n v3 = $5 AND\n v4 = $6 AND\n v5 = $7", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53" -} diff --git a/core/governance/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json b/core/governance/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json deleted file mode 100644 index 4d06843d1..000000000 --- a/core/governance/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM casbin_rule", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5" -} diff --git a/core/governance/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json b/core/governance/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json deleted file mode 100644 index 75c6da350..000000000 --- a/core/governance/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "CREATE TABLE IF NOT EXISTS casbin_rule (\n id SERIAL PRIMARY KEY,\n ptype VARCHAR NOT NULL,\n v0 VARCHAR NOT NULL,\n v1 VARCHAR NOT NULL,\n v2 VARCHAR NOT NULL,\n v3 VARCHAR NOT NULL,\n v4 VARCHAR NOT NULL,\n v5 VARCHAR NOT NULL,\n CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)\n );\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107" -} diff --git a/core/governance/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json b/core/governance/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json deleted file mode 100644 index ce229dc41..000000000 --- a/core/governance/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v4 is NULL OR v4 = COALESCE($2,v4)) AND\n (v5 is NULL OR v5 = COALESCE($3,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f" -} diff --git a/core/governance/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json b/core/governance/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json deleted file mode 100644 index 4c4c1df2a..000000000 --- a/core/governance/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v1 is NULL OR v1 = COALESCE($2,v1)) AND\n (v2 is NULL OR v2 = COALESCE($3,v2)) AND\n (v3 is NULL OR v3 = COALESCE($4,v3)) AND\n (v4 is NULL OR v4 = COALESCE($5,v4)) AND\n (v5 is NULL OR v5 = COALESCE($6,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a" -} diff --git a/core/governance/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/core/governance/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/core/governance/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/core/governance/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json b/core/governance/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json deleted file mode 100644 index ef54cdb3b..000000000 --- a/core/governance/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v0 is NULL OR v0 = COALESCE($2,v0)) AND\n (v1 is NULL OR v1 = COALESCE($3,v1)) AND\n (v2 is NULL OR v2 = COALESCE($4,v2)) AND\n (v3 is NULL OR v3 = COALESCE($5,v3)) AND\n (v4 is NULL OR v4 = COALESCE($6,v4)) AND\n (v5 is NULL OR v5 = COALESCE($7,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119" -} diff --git a/core/governance/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json b/core/governance/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json deleted file mode 100644 index 0daaa8a87..000000000 --- a/core/governance/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v2 is NULL OR v2 = COALESCE($2,v2)) AND\n (v3 is NULL OR v3 = COALESCE($3,v3)) AND\n (v4 is NULL OR v4 = COALESCE($4,v4)) AND\n (v5 is NULL OR v5 = COALESCE($5,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b" -} diff --git a/core/governance/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json b/core/governance/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json deleted file mode 100644 index 4a5f7e808..000000000 --- a/core/governance/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v5 is NULL OR v5 = COALESCE($2,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b" -} diff --git a/core/governance/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json b/core/governance/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json deleted file mode 100644 index 897ae5268..000000000 --- a/core/governance/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * from casbin_rule WHERE (\n ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )\n OR (\n ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345" -} diff --git a/lana/app/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json b/lana/app/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json deleted file mode 100644 index eb3a84f04..000000000 --- a/lana/app/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )\n VALUES ( $1, $2, $3, $4, $5, $6, $7 )", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164" -} diff --git a/lana/app/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json b/lana/app/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json deleted file mode 100644 index 1ea12e396..000000000 --- a/lana/app/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v3 is NULL OR v3 = COALESCE($2,v3)) AND\n (v4 is NULL OR v4 = COALESCE($3,v4)) AND\n (v5 is NULL OR v5 = COALESCE($4,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0" -} diff --git a/lana/app/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json b/lana/app/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json deleted file mode 100644 index 8046c5db1..000000000 --- a/lana/app/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9" -} diff --git a/lana/app/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json b/lana/app/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json deleted file mode 100644 index e246e53b4..000000000 --- a/lana/app/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n v0 = $2 AND\n v1 = $3 AND\n v2 = $4 AND\n v3 = $5 AND\n v4 = $6 AND\n v5 = $7", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53" -} diff --git a/lana/app/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json b/lana/app/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json deleted file mode 100644 index 4d06843d1..000000000 --- a/lana/app/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM casbin_rule", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5" -} diff --git a/lana/app/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json b/lana/app/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json deleted file mode 100644 index 75c6da350..000000000 --- a/lana/app/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "CREATE TABLE IF NOT EXISTS casbin_rule (\n id SERIAL PRIMARY KEY,\n ptype VARCHAR NOT NULL,\n v0 VARCHAR NOT NULL,\n v1 VARCHAR NOT NULL,\n v2 VARCHAR NOT NULL,\n v3 VARCHAR NOT NULL,\n v4 VARCHAR NOT NULL,\n v5 VARCHAR NOT NULL,\n CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)\n );\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107" -} diff --git a/lana/app/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json b/lana/app/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json deleted file mode 100644 index ce229dc41..000000000 --- a/lana/app/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v4 is NULL OR v4 = COALESCE($2,v4)) AND\n (v5 is NULL OR v5 = COALESCE($3,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f" -} diff --git a/lana/app/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json b/lana/app/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json deleted file mode 100644 index 4c4c1df2a..000000000 --- a/lana/app/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v1 is NULL OR v1 = COALESCE($2,v1)) AND\n (v2 is NULL OR v2 = COALESCE($3,v2)) AND\n (v3 is NULL OR v3 = COALESCE($4,v3)) AND\n (v4 is NULL OR v4 = COALESCE($5,v4)) AND\n (v5 is NULL OR v5 = COALESCE($6,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a" -} diff --git a/lana/dashboard/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json b/lana/app/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json similarity index 62% rename from lana/dashboard/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json rename to lana/app/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json index ebb5761b9..79ca8a1a7 100644 --- a/lana/dashboard/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json +++ b/lana/app/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH selected_jobs AS (\n SELECT je.id, je.execution_state_json AS data_json\n FROM job_executions je\n JOIN jobs ON je.id = jobs.id\n WHERE reschedule_after < $2::timestamptz\n AND je.state = 'pending'\n LIMIT $1\n FOR UPDATE\n )\n UPDATE job_executions AS je\n SET state = 'running', reschedule_after = $2::timestamptz + $3::interval\n FROM selected_jobs\n WHERE je.id = selected_jobs.id\n RETURNING je.id AS \"id!: JobId\", selected_jobs.data_json, je.attempt_index\n ", + "query": "\n WITH selected_jobs AS (\n SELECT je.id, je.execution_state_json AS data_json\n FROM job_executions je\n JOIN jobs ON je.id = jobs.id\n WHERE reschedule_after < $2::timestamptz\n AND je.state = 'pending'\n ORDER BY reschedule_after ASC\n LIMIT $1\n FOR UPDATE\n )\n UPDATE job_executions AS je\n SET state = 'running', reschedule_after = $2::timestamptz + $3::interval\n FROM selected_jobs\n WHERE je.id = selected_jobs.id\n RETURNING je.id AS \"id!: JobId\", selected_jobs.data_json, je.attempt_index\n ", "describe": { "columns": [ { @@ -32,5 +32,5 @@ false ] }, - "hash": "96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c" + "hash": "5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d" } diff --git a/lana/app/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/lana/app/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/lana/app/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/lana/app/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json b/lana/app/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json deleted file mode 100644 index ef54cdb3b..000000000 --- a/lana/app/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v0 is NULL OR v0 = COALESCE($2,v0)) AND\n (v1 is NULL OR v1 = COALESCE($3,v1)) AND\n (v2 is NULL OR v2 = COALESCE($4,v2)) AND\n (v3 is NULL OR v3 = COALESCE($5,v3)) AND\n (v4 is NULL OR v4 = COALESCE($6,v4)) AND\n (v5 is NULL OR v5 = COALESCE($7,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119" -} diff --git a/lana/app/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json b/lana/app/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json deleted file mode 100644 index 0daaa8a87..000000000 --- a/lana/app/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v2 is NULL OR v2 = COALESCE($2,v2)) AND\n (v3 is NULL OR v3 = COALESCE($3,v3)) AND\n (v4 is NULL OR v4 = COALESCE($4,v4)) AND\n (v5 is NULL OR v5 = COALESCE($5,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b" -} diff --git a/lana/app/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json b/lana/app/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json deleted file mode 100644 index 4a5f7e808..000000000 --- a/lana/app/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v5 is NULL OR v5 = COALESCE($2,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b" -} diff --git a/lana/app/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json b/lana/app/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json deleted file mode 100644 index 897ae5268..000000000 --- a/lana/app/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * from casbin_rule WHERE (\n ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )\n OR (\n ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345" -} diff --git a/lana/app/Cargo.toml b/lana/app/Cargo.toml index 1aab3c55b..5c86ee3db 100644 --- a/lana/app/Cargo.toml +++ b/lana/app/Cargo.toml @@ -25,6 +25,7 @@ outbox = { path = "../../lib/outbox" } audit = { path = "../../lib/audit" } authz = { path = "../../lib/authz" } +cala-ledger = { workspace = true } es-entity = { workspace = true, features = ["graphql"] } sim-time = { workspace = true, optional = true } diff --git a/lana/app/migrations/20231208110808_cala_ledger_setup.sql b/lana/app/migrations/20231208110808_cala_ledger_setup.sql new file mode 100644 index 000000000..4cf7d1e21 --- /dev/null +++ b/lana/app/migrations/20231208110808_cala_ledger_setup.sql @@ -0,0 +1,254 @@ +CREATE TYPE DebitOrCredit AS ENUM ('debit', 'credit'); +CREATE TYPE Status AS ENUM ('active', 'locked'); +CREATE TYPE Layer AS ENUM ('settled', 'pending', 'encumbrance'); + +CREATE TABLE cala_accounts ( + id UUID PRIMARY KEY, + code VARCHAR UNIQUE NOT NULL, + name VARCHAR NOT NULL, + external_id VARCHAR UNIQUE, + data_source_id UUID NOT NULL, + normal_balance_type DebitOrCredit NOT NULL, -- For quick lookup when querying balances + eventually_consistent BOOLEAN NOT NULL, -- For balance locking + latest_values JSONB NOT NULL, -- Cached for quicker velocity enforcement + created_at TIMESTAMPTZ NOT NULL +); +CREATE INDEX idx_cala_accounts_name ON cala_accounts (name); + +CREATE TABLE cala_account_events ( + id UUID NOT NULL REFERENCES cala_accounts(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_journals ( + id UUID PRIMARY KEY, + name VARCHAR NOT NULL, + data_source_id UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL +); +CREATE INDEX idx_cala_journals_name ON cala_journals (name); + +CREATE TABLE cala_journal_events ( + id UUID NOT NULL REFERENCES cala_journals(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL, + UNIQUE(id, sequence) +); + +CREATE TABLE cala_account_sets ( + id UUID PRIMARY KEY REFERENCES cala_accounts(id), + journal_id UUID NOT NULL REFERENCES cala_journals(id), + name VARCHAR NOT NULL, + data_source_id UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE INDEX idx_cala_account_sets_name ON cala_account_sets (name); + + +CREATE TABLE cala_account_set_events ( + id UUID NOT NULL REFERENCES cala_account_sets(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_account_set_member_accounts ( + account_set_id UUID NOT NULL REFERENCES cala_account_sets(id), + member_account_id UUID NOT NULL REFERENCES cala_accounts(id), + transitive BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(account_set_id, member_account_id) +); + +CREATE TABLE cala_account_set_member_account_sets ( + account_set_id UUID NOT NULL REFERENCES cala_account_sets(id), + member_account_set_id UUID NOT NULL REFERENCES cala_account_sets(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(account_set_id, member_account_set_id) +); + +CREATE TABLE cala_tx_templates ( + id UUID PRIMARY KEY, + data_source_id UUID NOT NULL, + code VARCHAR NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE TABLE cala_tx_template_events ( + id UUID NOT NULL, + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence), + FOREIGN KEY (id) REFERENCES cala_tx_templates(id) +); + +CREATE TABLE cala_transactions ( + id UUID PRIMARY KEY, + data_source_id UUID NOT NULL, + journal_id UUID NOT NULL, + tx_template_id UUID NOT NULL, + external_id VARCHAR DEFAULT NULL, + correlation_id VARCHAR NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + FOREIGN KEY (journal_id) REFERENCES cala_journals(id), + FOREIGN KEY (tx_template_id) REFERENCES cala_tx_templates(id) +); + +CREATE TABLE cala_transaction_events ( + id UUID NOT NULL REFERENCES cala_transactions(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_entries ( + id UUID PRIMARY KEY, + journal_id UUID NOT NULL REFERENCES cala_journals(id), + account_id UUID NOT NULL REFERENCES cala_accounts(id), + transaction_id UUID NOT NULL, + data_source_id UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE INDEX idx_cala_entries_transaction_id ON cala_entries (transaction_id); + +CREATE TABLE cala_entry_events ( + id UUID NOT NULL REFERENCES cala_entries(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_current_balances ( + journal_id UUID NOT NULL REFERENCES cala_journals(id), + account_id UUID NOT NULL REFERENCES cala_accounts(id), + currency VARCHAR NOT NULL, + latest_version INT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(journal_id, account_id, currency) +); + +CREATE TABLE cala_balance_history ( + journal_id UUID NOT NULL, + account_id UUID NOT NULL, + latest_entry_id UUID NOT NULL REFERENCES cala_entries(id), + currency VARCHAR NOT NULL, + version INT NOT NULL, + values JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(journal_id, account_id, currency, version), + FOREIGN KEY (journal_id, account_id, currency) REFERENCES cala_current_balances(journal_id, account_id, currency) +); +CREATE INDEX idx_cala_balance_history_recorded_at ON cala_balance_history (recorded_at); + +CREATE TABLE cala_velocity_limits ( + id UUID PRIMARY KEY, + name VARCHAR NOT NULL, + data_source_id UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE INDEX idx_cala_velocity_limits_name ON cala_velocity_limits (name); + + +CREATE TABLE cala_velocity_limit_events ( + id UUID NOT NULL REFERENCES cala_velocity_limits(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_velocity_controls ( + id UUID PRIMARY KEY, + name VARCHAR NOT NULL, + data_source_id UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE INDEX idx_cala_velocity_controls_name ON cala_velocity_controls (name); + + +CREATE TABLE cala_velocity_control_events ( + id UUID NOT NULL REFERENCES cala_velocity_controls(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(id, sequence) +); + +CREATE TABLE cala_velocity_control_limits ( + velocity_control_id UUID NOT NULL REFERENCES cala_velocity_controls(id), + velocity_limit_id UUID NOT NULL REFERENCES cala_velocity_limits(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(velocity_control_id, velocity_limit_id) +); + +CREATE TABLE cala_velocity_account_controls ( + account_id UUID NOT NULL REFERENCES cala_accounts(id), + velocity_control_id UUID NOT NULL REFERENCES cala_velocity_controls(id), + values JSONB NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(account_id, velocity_control_id) +); + +CREATE TABLE cala_velocity_current_balances ( + journal_id UUID NOT NULL REFERENCES cala_journals(id), + account_id UUID NOT NULL REFERENCES cala_accounts(id), + currency VARCHAR NOT NULL, + velocity_control_id UUID NOT NULL REFERENCES cala_velocity_controls(id), + velocity_limit_id UUID NOT NULL REFERENCES cala_velocity_limits(id), + partition_window JSONB NOT NULL, + latest_version INT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(partition_window, currency, journal_id, account_id, velocity_limit_id, velocity_control_id) +); + +CREATE TABLE cala_velocity_balance_history ( + journal_id UUID NOT NULL, + account_id UUID NOT NULL, + currency VARCHAR NOT NULL, + velocity_control_id UUID NOT NULL, + velocity_limit_id UUID NOT NULL, + partition_window JSONB NOT NULL, + latest_entry_id UUID NOT NULL REFERENCES cala_entries(id), + version INT NOT NULL, + values JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(partition_window, currency, journal_id, account_id, velocity_limit_id, velocity_control_id, version), + FOREIGN KEY (partition_window, currency, journal_id, account_id, velocity_limit_id, velocity_control_id) REFERENCES cala_velocity_current_balances(partition_window, currency, journal_id, account_id, velocity_limit_id, velocity_control_id) +); + +CREATE TABLE cala_outbox_events ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + sequence BIGSERIAL UNIQUE, + payload JSONB, + recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE FUNCTION notify_cala_outbox_events() RETURNS TRIGGER AS $$ +DECLARE + payload TEXT; +BEGIN + payload := row_to_json(NEW); + PERFORM pg_notify('cala_outbox_events', payload); + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER cala_outbox_events AFTER INSERT ON cala_outbox_events + FOR EACH ROW EXECUTE FUNCTION notify_cala_outbox_events(); diff --git a/lana/app/migrations/20240517074612_core_setup.sql b/lana/app/migrations/20240517074612_core_setup.sql index 5326d9117..041d09aa5 100644 --- a/lana/app/migrations/20240517074612_core_setup.sql +++ b/lana/app/migrations/20240517074612_core_setup.sql @@ -46,6 +46,54 @@ CREATE TABLE approval_process_events ( UNIQUE(id, sequence) ); +CREATE TABLE deposit_accounts ( + id UUID PRIMARY KEY, + account_holder_id VARCHAR NOT NULL, + created_at TIMESTAMPTZ NOT NULL +); + +CREATE TABLE deposit_account_events ( + id UUID NOT NULL REFERENCES deposit_accounts(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL, + UNIQUE(id, sequence) +); + +CREATE TABLE core_deposits ( + id UUID PRIMARY KEY, + deposit_account_id UUID NOT NULL REFERENCES deposit_accounts(id), + reference VARCHAR NOT NULL UNIQUE, + created_at TIMESTAMPTZ NOT NULL +); + +CREATE TABLE core_deposit_events ( + id UUID NOT NULL REFERENCES core_deposits(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL, + UNIQUE(id, sequence) +); + +CREATE TABLE core_withdrawals ( + id UUID PRIMARY KEY, + deposit_account_id UUID NOT NULL REFERENCES deposit_accounts(id), + approval_process_id UUID REFERENCES approval_processes(id), + reference VARCHAR NOT NULL UNIQUE, + created_at TIMESTAMPTZ NOT NULL +); + +CREATE TABLE core_withdrawal_events ( + id UUID NOT NULL REFERENCES core_withdrawals(id), + sequence INT NOT NULL, + event_type VARCHAR NOT NULL, + event JSONB NOT NULL, + recorded_at TIMESTAMPTZ NOT NULL, + UNIQUE(id, sequence) +); + CREATE TABLE customers ( id UUID PRIMARY KEY, email VARCHAR NOT NULL UNIQUE, diff --git a/lana/app/src/app/error.rs b/lana/app/src/app/error.rs index 0f9f6fe41..72813e390 100644 --- a/lana/app/src/app/error.rs +++ b/lana/app/src/app/error.rs @@ -30,4 +30,6 @@ pub enum ApplicationError { WithdrawalError(#[from] crate::withdrawal::error::WithdrawalError), #[error("ApplicationError - DashboardError: {0}")] DashboardError(#[from] dashboard::error::DashboardError), + #[error("ApplicationError - CalaInit: {0}")] + CalaError(#[from] cala_ledger::error::LedgerError), } diff --git a/lana/app/src/app/mod.rs b/lana/app/src/app/mod.rs index 822781cb8..90c383223 100644 --- a/lana/app/src/app/mod.rs +++ b/lana/app/src/app/mod.rs @@ -85,6 +85,12 @@ impl LanaApp { let documents = Documents::new(&pool, &storage, &authz); let report = Reports::init(&pool, &config.report, &authz, &jobs, &storage, &export).await?; let users = Users::init(&pool, &authz, &outbox, config.user.superuser_email).await?; + let cala_config = cala_ledger::CalaLedgerConfig::builder() + .pool(pool.clone()) + .exec_migrations(false) + .build() + .expect("cala config"); + let cala = cala_ledger::CalaLedger::init(cala_config).await?; let credit_facilities = CreditFacilities::init( &pool, config.credit_facility, @@ -96,6 +102,8 @@ impl LanaApp { &ledger, &price, &outbox, + &cala, + cala_ledger::JournalId::new(), ) .await?; let terms_templates = TermsTemplates::new(&pool, &authz, &export); diff --git a/lana/app/src/credit_facility/error.rs b/lana/app/src/credit_facility/error.rs index 48a56c7d5..00361391a 100644 --- a/lana/app/src/credit_facility/error.rs +++ b/lana/app/src/credit_facility/error.rs @@ -6,6 +6,8 @@ use crate::primitives::{CustomerId, Satoshis, UsdCents}; pub enum CreditFacilityError { #[error("CreditFacilityError - Sqlx: {0}")] Sqlx(#[from] sqlx::Error), + #[error("CreditFacilityError - CreditError: {0}")] + CreditLedgerError(#[from] super::ledger::error::CreditLedgerError), #[error("CreditFacilityError - EsEntityError: {0}")] EsEntityError(es_entity::EsEntityError), #[error("FacilityError - CursorDestructureError: {0}")] diff --git a/lana/app/src/credit_facility/ledger/credit_facility_accounts.rs b/lana/app/src/credit_facility/ledger/credit_facility_accounts.rs new file mode 100644 index 000000000..58af46fb4 --- /dev/null +++ b/lana/app/src/credit_facility/ledger/credit_facility_accounts.rs @@ -0,0 +1,45 @@ +use serde::{Deserialize, Serialize}; + +use cala_ledger::AccountId as LedgerAccountId; + +use crate::primitives::{Satoshis, UsdCents}; + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub struct CreditFacilityAccountIds { + pub facility_account_id: LedgerAccountId, + pub disbursed_receivable_account_id: LedgerAccountId, + pub collateral_account_id: LedgerAccountId, + pub interest_receivable_account_id: LedgerAccountId, + pub interest_account_id: LedgerAccountId, + pub fee_income_account_id: LedgerAccountId, +} + +impl CreditFacilityAccountIds { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + facility_account_id: LedgerAccountId::new(), + disbursed_receivable_account_id: LedgerAccountId::new(), + collateral_account_id: LedgerAccountId::new(), + interest_receivable_account_id: LedgerAccountId::new(), + interest_account_id: LedgerAccountId::new(), + fee_income_account_id: LedgerAccountId::new(), + } + } +} + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub struct CreditFacilityLedgerBalance { + pub facility: UsdCents, + pub collateral: Satoshis, + pub disbursed: UsdCents, + pub disbursed_receivable: UsdCents, + pub interest: UsdCents, + pub interest_receivable: UsdCents, +} + +impl CreditFacilityLedgerBalance { + pub fn check_disbursal_amount(&self, amount: UsdCents) -> bool { + amount < self.facility + } +} diff --git a/lana/app/src/credit_facility/ledger/error.rs b/lana/app/src/credit_facility/ledger/error.rs new file mode 100644 index 000000000..29def72e7 --- /dev/null +++ b/lana/app/src/credit_facility/ledger/error.rs @@ -0,0 +1,17 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum CreditLedgerError { + #[error("DepositLedgerError - Sqlx: {0}")] + Sqlx(#[from] sqlx::Error), + #[error("DepositLedgerError - CalaLedger: {0}")] + CalaLedger(#[from] cala_ledger::error::LedgerError), + #[error("DepositLedgerError - CalaAccountError: {0}")] + CalaAccount(#[from] cala_ledger::account::error::AccountError), + #[error("DepositLedgerError - CalaTxTemplateError: {0}")] + CalaTxTemplate(#[from] cala_ledger::tx_template::error::TxTemplateError), + #[error("DepositLedgerError - CalaBalanceError: {0}")] + CalaBalance(#[from] cala_ledger::balance::error::BalanceError), + #[error("DepositLedgerError - ConversionError: {0}")] + ConversionError(#[from] core_money::ConversionError), +} diff --git a/lana/app/src/credit_facility/ledger/mod.rs b/lana/app/src/credit_facility/ledger/mod.rs new file mode 100644 index 000000000..659149706 --- /dev/null +++ b/lana/app/src/credit_facility/ledger/mod.rs @@ -0,0 +1,184 @@ +mod credit_facility_accounts; +pub mod error; +mod templates; + +use cala_ledger::{account::NewAccount, CalaLedger, Currency, JournalId}; + +use crate::primitives::{CreditFacilityId, Satoshis, UsdCents}; + +pub use credit_facility_accounts::*; +use error::*; + +#[derive(Clone)] +pub struct CreditLedger { + cala: CalaLedger, + journal_id: JournalId, + usd: Currency, + btc: Currency, +} + +impl CreditLedger { + pub async fn init(cala: &CalaLedger, journal_id: JournalId) -> Result { + templates::AddCollateral::init(cala).await?; + templates::RemoveCollateral::init(cala).await?; + + Ok(Self { + cala: cala.clone(), + journal_id, + usd: "USD".parse().expect("Could not parse 'USD'"), + btc: "BTC".parse().expect("Could not parse 'BTC'"), + }) + } + + pub async fn create_accounts_for_credit_facility( + &self, + op: es_entity::DbOp<'_>, + credit_facility_id: CreditFacilityId, + CreditFacilityAccountIds { + facility_account_id, + disbursed_receivable_account_id, + collateral_account_id, + interest_receivable_account_id, + interest_account_id, + fee_income_account_id, + }: CreditFacilityAccountIds, + ) -> Result<(), CreditLedgerError> { + let mut op = self.cala.ledger_operation_from_db_op(op); + let new_accounts = vec![ + NewAccount::builder() + .id(collateral_account_id) + .name("Credit Facility Collateral Account") + .code(format!("CREDIT_FACILITY.COLLATERAL.{}", credit_facility_id)) + .build() + .expect("new account"), + NewAccount::builder() + .id(facility_account_id) + .name("Off-Balance-Sheet Facility Account for Credit Facility") + .code(format!( + "CREDIT_FACILITY.OBS_FACILITY.{}", + credit_facility_id + )) + .build() + .expect("new account"), + NewAccount::builder() + .id(disbursed_receivable_account_id) + .name("Disbursed Receivable Account for Credit Facility") + .code(format!( + "CREDIT_FACILITY.DISBURSED_RECEIVABLE.{}", + credit_facility_id + )) + .build() + .expect("new account"), + NewAccount::builder() + .id(interest_receivable_account_id) + .name("Interest Receivable Account for Credit Facility") + .code(format!( + "CREDIT_FACILITY.INTEREST_RECEIVABLE.{}", + credit_facility_id + )) + .build() + .expect("new account"), + NewAccount::builder() + .id(interest_account_id) + .name("Interest Income for Credit Facility") + .code(format!( + "CREDIT_FACILITY.INTEREST_INCOME.{}", + credit_facility_id + )) + .build() + .expect("new account"), + NewAccount::builder() + .id(fee_income_account_id) + .name("Fee Income for Credit Facility") + .code(format!("CREDIT_FACILITY.FEE_INCOME.{}", credit_facility_id)) + .build() + .expect("new account"), + ]; + + self.cala + .accounts() + .create_all_in_op(&mut op, new_accounts) + .await?; + + op.commit().await?; + + Ok(()) + } + + pub async fn get_credit_facility_balance( + &self, + CreditFacilityAccountIds { + facility_account_id, + disbursed_receivable_account_id, + collateral_account_id, + interest_receivable_account_id, + .. + }: CreditFacilityAccountIds, + ) -> Result { + let facility_id = (self.journal_id, facility_account_id, self.usd); + let collateral_id = (self.journal_id, collateral_account_id, self.btc); + let disbursed_receivable_id = (self.journal_id, disbursed_receivable_account_id, self.btc); + let interest_receivable_id = (self.journal_id, interest_receivable_account_id, self.btc); + let balances = self + .cala + .balances() + .find_all(&[ + facility_id, + collateral_id, + disbursed_receivable_id, + interest_receivable_id, + ]) + .await?; + let facility = if let Some(b) = balances.get(&facility_id) { + UsdCents::try_from_usd(b.settled())? + } else { + UsdCents::ZERO + }; + let disbursed = if let Some(b) = balances.get(&disbursed_receivable_id) { + UsdCents::try_from_usd(b.details.settled.dr_balance)? + } else { + UsdCents::ZERO + }; + let disbursed_receivable = if let Some(b) = balances.get(&disbursed_receivable_id) { + UsdCents::try_from_usd(b.settled())? + } else { + UsdCents::ZERO + }; + let interest = if let Some(b) = balances.get(&interest_receivable_id) { + UsdCents::try_from_usd(b.details.settled.dr_balance)? + } else { + UsdCents::ZERO + }; + let interest_receivable = if let Some(b) = balances.get(&interest_receivable_id) { + UsdCents::try_from_usd(b.settled())? + } else { + UsdCents::ZERO + }; + let collateral = if let Some(b) = balances.get(&collateral_id) { + Satoshis::try_from_btc(b.settled())? + } else { + Satoshis::ZERO + }; + Ok(CreditFacilityLedgerBalance { + facility, + collateral, + disbursed, + disbursed_receivable, + interest, + interest_receivable, + }) + } + + pub async fn update_credit_facility_collateral( + &self, + // CreditFacilityCollateralUpdate { + // tx_id, + // credit_facility_account_ids, + // abs_diff, + // tx_ref, + // action, + // }: CreditFacilityCollateralUpdate, + ) -> Result<(), CreditLedgerError> { + unimplemented!() + } +} diff --git a/lana/app/src/credit_facility/ledger/templates/add_collateral.rs b/lana/app/src/credit_facility/ledger/templates/add_collateral.rs new file mode 100644 index 000000000..e30ba642a --- /dev/null +++ b/lana/app/src/credit_facility/ledger/templates/add_collateral.rs @@ -0,0 +1,128 @@ +use rust_decimal::Decimal; +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::credit_facility::ledger::error::*; + +pub const ADD_COLLATERAL_CODE: &str = "ADD_COLLATERAL"; + +#[derive(Debug)] +pub struct AddCollateralParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, +} + +impl AddCollateralParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("collateral_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("bank_collateral_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + AddCollateralParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + credit_account_id, + }: AddCollateralParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct AddCollateral; + +impl AddCollateral { + #[instrument(name = "ledger.add_collateral.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), CreditLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Record a deposit'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + NewTxTemplateEntry::builder() + .entry_type("'ADD_COLLATERAL_DR'") + .currency("params.currency") + .account_id("params.bank_collateral_account_id") + .direction("DEBIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'ADD_COLLATERAL_CR'") + .currency("params.currency") + .account_id("params.collateral_account_id") + .direction("CREDIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = AddCollateralParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(ADD_COLLATERAL_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/lana/app/src/credit_facility/ledger/templates/mod.rs b/lana/app/src/credit_facility/ledger/templates/mod.rs new file mode 100644 index 000000000..eaadd1bd7 --- /dev/null +++ b/lana/app/src/credit_facility/ledger/templates/mod.rs @@ -0,0 +1,5 @@ +mod add_collateral; +mod remove_collateral; + +pub use add_collateral::*; +pub use remove_collateral::*; diff --git a/lana/app/src/credit_facility/ledger/templates/remove_collateral.rs b/lana/app/src/credit_facility/ledger/templates/remove_collateral.rs new file mode 100644 index 000000000..5ef235c14 --- /dev/null +++ b/lana/app/src/credit_facility/ledger/templates/remove_collateral.rs @@ -0,0 +1,128 @@ +use rust_decimal::Decimal; +use tracing::instrument; + +use cala_ledger::{ + tx_template::{error::TxTemplateError, Params, *}, + *, +}; + +use crate::credit_facility::ledger::error::*; + +pub const REMOVE_COLLATERAL_CODE: &str = "REMOVE_COLLATERAL"; + +#[derive(Debug)] +pub struct RemoveCollateralParams { + pub journal_id: JournalId, + pub currency: Currency, + pub amount: Decimal, + pub deposit_omnibus_account_id: AccountId, + pub credit_account_id: AccountId, +} + +impl RemoveCollateralParams { + pub fn defs() -> Vec { + vec![ + NewParamDefinition::builder() + .name("journal_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("currency") + .r#type(ParamDataType::String) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("amount") + .r#type(ParamDataType::Decimal) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("collateral_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("bank_collateral_account_id") + .r#type(ParamDataType::Uuid) + .build() + .unwrap(), + NewParamDefinition::builder() + .name("effective") + .r#type(ParamDataType::Date) + .build() + .unwrap(), + ] + } +} + +impl From for Params { + fn from( + RemoveCollateralParams { + journal_id, + currency, + amount, + deposit_omnibus_account_id, + credit_account_id, + }: RemoveCollateralParams, + ) -> Self { + let mut params = Self::default(); + params.insert("journal_id", journal_id); + params.insert("currency", currency); + params.insert("amount", amount); + params.insert("deposit_omnibus_account_id", deposit_omnibus_account_id); + params.insert("credit_account_id", credit_account_id); + params.insert("effective", chrono::Utc::now().date_naive()); + + params + } +} + +pub struct RemoveCollateral; + +impl RemoveCollateral { + #[instrument(name = "ledger.add_collateral.init", skip_all)] + pub async fn init(ledger: &CalaLedger) -> Result<(), CreditLedgerError> { + let tx_input = NewTxTemplateTransaction::builder() + .journal_id("params.journal_id") + .effective("params.effective") + .description("'Record a deposit'") + .build() + .expect("Couldn't build TxInput"); + let entries = vec![ + NewTxTemplateEntry::builder() + .entry_type("'REMOVE_COLLATERAL_DR'") + .currency("params.currency") + .account_id("params.collateral_account_id") + .direction("DEBIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + NewTxTemplateEntry::builder() + .entry_type("'REMOVE_COLLATERAL_CR'") + .currency("params.currency") + .account_id("params.bank_collateral_account_id") + .direction("CREDIT") + .layer("SETTLED") + .units("params.amount") + .build() + .expect("Couldn't build entry"), + ]; + + let params = RemoveCollateralParams::defs(); + let template = NewTxTemplate::builder() + .id(TxTemplateId::new()) + .code(REMOVE_COLLATERAL_CODE) + .transaction(tx_input) + .entries(entries) + .params(params) + .build() + .expect("Couldn't build template"); + match ledger.tx_templates().create(template).await { + Err(TxTemplateError::DuplicateCode) => Ok(()), + Err(e) => Err(e.into()), + Ok(_) => Ok(()), + } + } +} diff --git a/lana/app/src/credit_facility/mod.rs b/lana/app/src/credit_facility/mod.rs index bdd37ef8d..d1877832c 100644 --- a/lana/app/src/credit_facility/mod.rs +++ b/lana/app/src/credit_facility/mod.rs @@ -5,6 +5,7 @@ pub mod error; mod history; mod interest_accrual; mod jobs; +pub mod ledger; mod processes; mod publisher; mod repo; @@ -12,6 +13,8 @@ mod repo; use std::collections::HashMap; use authz::PermissionCheck; +use cala_ledger::CalaLedger; +use tracing::instrument; use crate::{ audit::AuditInfo, @@ -37,6 +40,7 @@ use error::*; pub use history::*; pub use interest_accrual::*; use jobs::*; +use ledger::CreditLedger; use processes::activate_credit_facility::*; pub use processes::approve_credit_facility::*; pub use processes::approve_disbursal::*; @@ -46,7 +50,6 @@ pub use repo::{ credit_facility_cursor::*, CreditFacilitiesSortBy, FindManyCreditFacilities, ListDirection, Sort, }; -use tracing::instrument; #[derive(Clone)] pub struct CreditFacilities { @@ -55,7 +58,8 @@ pub struct CreditFacilities { credit_facility_repo: CreditFacilityRepo, disbursal_repo: DisbursalRepo, governance: Governance, - ledger: Ledger, + gql_ledger: Ledger, + ledger: CreditLedger, price: Price, config: CreditFacilityConfig, approve_disbursal: ApproveDisbursal, @@ -72,9 +76,11 @@ impl CreditFacilities { export: &Export, authz: &Authorization, customers: &Customers, - ledger: &Ledger, + gql_ledger: &Ledger, price: &Price, outbox: &Outbox, + cala: &CalaLedger, + journal_id: cala_ledger::JournalId, ) -> Result { let publisher = CreditFacilityPublisher::new(export, outbox); let credit_facility_repo = CreditFacilityRepo::new(pool, &publisher); @@ -84,14 +90,14 @@ impl CreditFacilities { &credit_facility_repo, authz.audit(), governance, - ledger, + gql_ledger, ); let approve_credit_facility = ApproveCreditFacility::new(&credit_facility_repo, authz.audit(), governance); let activate_credit_facility = ActivateCreditFacility::new( &credit_facility_repo, &disbursal_repo, - ledger, + gql_ledger, price, jobs, authz.audit(), @@ -110,14 +116,14 @@ impl CreditFacilities { .await?; jobs.add_initializer( interest_incurrences::CreditFacilityProcessingJobInitializer::new( - ledger, + gql_ledger, credit_facility_repo.clone(), authz.audit(), ), ); jobs.add_initializer( interest_accruals::CreditFacilityProcessingJobInitializer::new( - ledger, + gql_ledger, credit_facility_repo.clone(), jobs, authz.audit(), @@ -143,13 +149,16 @@ impl CreditFacilities { .await; let _ = governance.init_policy(APPROVE_DISBURSAL_PROCESS).await; + let ledger = CreditLedger::init(cala, journal_id).await?; + Ok(Self { authz: authz.clone(), customers: customers.clone(), credit_facility_repo, disbursal_repo, governance: governance.clone(), - ledger: ledger.clone(), + gql_ledger: gql_ledger.clone(), + ledger, price: price.clone(), config, approve_disbursal, @@ -215,11 +224,13 @@ impl CreditFacilities { .create_in_op(&mut db, new_credit_facility) .await?; self.ledger - .create_accounts_for_credit_facility(credit_facility.id, credit_facility.account_ids) + .create_accounts_for_credit_facility( + db, + credit_facility.id, + credit_facility.account_ids, + ) .await?; - db.commit().await?; - Ok(credit_facility) } @@ -289,13 +300,11 @@ impl CreditFacilities { .find_by_id(credit_facility_id) .await?; - let ledger_balances = self + let balances = self .ledger .get_credit_facility_balance(credit_facility.account_ids) .await?; - credit_facility - .balances() - .check_against_ledger(ledger_balances)?; + credit_facility.balances().check_against_ledger(balances)?; credit_facility.balances().check_disbursal_amount(amount)?; @@ -405,13 +414,10 @@ impl CreditFacilities { .update_in_op(&mut db, &mut credit_facility) .await?; - self.ledger + self.gql_ledger .update_credit_facility_collateral(credit_facility_collateral_update) .await?; - self.credit_facility_repo - .update_in_op(&mut db, &mut credit_facility) - .await?; db.commit().await?; Ok(credit_facility) } @@ -454,7 +460,7 @@ impl CreditFacilities { .await?; let ledger_balances = self - .ledger + .gql_ledger .get_credit_facility_balance(credit_facility.account_ids) .await?; credit_facility @@ -466,14 +472,14 @@ impl CreditFacilities { .repo() .find_by_id(credit_facility.customer_id) .await?; - self.ledger + self.gql_ledger .get_customer_balance(customer.account_ids) .await? .check_withdraw_amount(amount)?; let repayment = credit_facility.initiate_repayment(amount)?; let executed_at = self - .ledger + .gql_ledger .record_credit_facility_repayment(repayment.clone()) .await?; credit_facility.confirm_repayment( @@ -492,13 +498,13 @@ impl CreditFacilities { Ok(credit_facility) } - // #[instrument(name = "credit_facility.list", skip(self), err)] + #[instrument(name = "credit_facility.list", skip(self), err)] pub async fn list( &self, sub: &Subject, query: es_entity::PaginatedQueryArgs, filter: FindManyCreditFacilities, - sort: impl Into>, + sort: impl Into> + std::fmt::Debug, ) -> Result< es_entity::PaginatedQueryRet, CreditFacilityError, @@ -681,7 +687,7 @@ impl CreditFacilities { let completion = credit_facility.initiate_completion()?; let executed_at = self - .ledger + .gql_ledger .complete_credit_facility(completion.clone()) .await?; credit_facility.confirm_completion( diff --git a/lana/app/src/ledger/credit_facility.rs b/lana/app/src/ledger/credit_facility.rs index 83b779112..f206d42ba 100644 --- a/lana/app/src/ledger/credit_facility.rs +++ b/lana/app/src/ledger/credit_facility.rs @@ -1,46 +1,13 @@ use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; use crate::{ - primitives::{CollateralAction, LedgerAccountId, LedgerTxId, Satoshis, UsdCents}, + primitives::{CollateralAction, LedgerTxId, Satoshis, UsdCents}, terms::InterestPeriod, }; use super::{cala::graphql::*, error::*, CustomerLedgerAccountIds}; -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub struct CreditFacilityAccountIds { - pub facility_account_id: LedgerAccountId, - pub disbursed_receivable_account_id: LedgerAccountId, - pub collateral_account_id: LedgerAccountId, - pub interest_receivable_account_id: LedgerAccountId, - pub interest_account_id: LedgerAccountId, - pub fee_income_account_id: LedgerAccountId, -} - -impl CreditFacilityAccountIds { - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self { - facility_account_id: LedgerAccountId::new(), - disbursed_receivable_account_id: LedgerAccountId::new(), - collateral_account_id: LedgerAccountId::new(), - interest_receivable_account_id: LedgerAccountId::new(), - interest_account_id: LedgerAccountId::new(), - fee_income_account_id: LedgerAccountId::new(), - } - } -} - -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub struct CreditFacilityLedgerBalance { - pub facility: UsdCents, - pub collateral: Satoshis, - pub disbursed: UsdCents, - pub disbursed_receivable: UsdCents, - pub interest: UsdCents, - pub interest_receivable: UsdCents, -} +pub use crate::credit_facility::ledger::{CreditFacilityAccountIds, CreditFacilityLedgerBalance}; impl TryFrom for CreditFacilityLedgerBalance { type Error = LedgerError; diff --git a/lana/app/tests/gcs.rs b/lana/app/tests/gcs.rs index 00e5462aa..4f85929c9 100644 --- a/lana/app/tests/gcs.rs +++ b/lana/app/tests/gcs.rs @@ -32,7 +32,7 @@ async fn upload_doc() -> anyhow::Result<()> { let _ = storage.upload(content, filename, "application/txt").await; let res = storage._list("".to_string()).await?; - assert!(res.first().is_some()); + assert!(!res.is_empty()); let count = res.len(); // generate link diff --git a/lana/dashboard/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json b/lana/dashboard/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json deleted file mode 100644 index eb3a84f04..000000000 --- a/lana/dashboard/.sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )\n VALUES ( $1, $2, $3, $4, $5, $6, $7 )", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164" -} diff --git a/lana/dashboard/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json b/lana/dashboard/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json deleted file mode 100644 index 1ea12e396..000000000 --- a/lana/dashboard/.sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v3 is NULL OR v3 = COALESCE($2,v3)) AND\n (v4 is NULL OR v4 = COALESCE($3,v4)) AND\n (v5 is NULL OR v5 = COALESCE($4,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0" -} diff --git a/lana/dashboard/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json b/lana/dashboard/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json deleted file mode 100644 index 8046c5db1..000000000 --- a/lana/dashboard/.sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9" -} diff --git a/lana/dashboard/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json b/lana/dashboard/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json deleted file mode 100644 index e246e53b4..000000000 --- a/lana/dashboard/.sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n v0 = $2 AND\n v1 = $3 AND\n v2 = $4 AND\n v3 = $5 AND\n v4 = $6 AND\n v5 = $7", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53" -} diff --git a/lana/dashboard/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json b/lana/dashboard/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json deleted file mode 100644 index 4d06843d1..000000000 --- a/lana/dashboard/.sqlx/query-3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM casbin_rule", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "3022cb733970ae5836ab3891367b209a7e1f0974242ecd0f55e5b0098152bad5" -} diff --git a/lana/dashboard/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json b/lana/dashboard/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json deleted file mode 100644 index 75c6da350..000000000 --- a/lana/dashboard/.sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "CREATE TABLE IF NOT EXISTS casbin_rule (\n id SERIAL PRIMARY KEY,\n ptype VARCHAR NOT NULL,\n v0 VARCHAR NOT NULL,\n v1 VARCHAR NOT NULL,\n v2 VARCHAR NOT NULL,\n v3 VARCHAR NOT NULL,\n v4 VARCHAR NOT NULL,\n v5 VARCHAR NOT NULL,\n CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)\n );\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107" -} diff --git a/lana/dashboard/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json b/lana/dashboard/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json deleted file mode 100644 index ce229dc41..000000000 --- a/lana/dashboard/.sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v4 is NULL OR v4 = COALESCE($2,v4)) AND\n (v5 is NULL OR v5 = COALESCE($3,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f" -} diff --git a/lana/dashboard/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json b/lana/dashboard/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json deleted file mode 100644 index 4c4c1df2a..000000000 --- a/lana/dashboard/.sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v1 is NULL OR v1 = COALESCE($2,v1)) AND\n (v2 is NULL OR v2 = COALESCE($3,v2)) AND\n (v3 is NULL OR v3 = COALESCE($4,v3)) AND\n (v4 is NULL OR v4 = COALESCE($5,v4)) AND\n (v5 is NULL OR v5 = COALESCE($6,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a" -} diff --git a/lana/app/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json b/lana/dashboard/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json similarity index 62% rename from lana/app/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json rename to lana/dashboard/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json index ebb5761b9..79ca8a1a7 100644 --- a/lana/app/.sqlx/query-96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c.json +++ b/lana/dashboard/.sqlx/query-5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH selected_jobs AS (\n SELECT je.id, je.execution_state_json AS data_json\n FROM job_executions je\n JOIN jobs ON je.id = jobs.id\n WHERE reschedule_after < $2::timestamptz\n AND je.state = 'pending'\n LIMIT $1\n FOR UPDATE\n )\n UPDATE job_executions AS je\n SET state = 'running', reschedule_after = $2::timestamptz + $3::interval\n FROM selected_jobs\n WHERE je.id = selected_jobs.id\n RETURNING je.id AS \"id!: JobId\", selected_jobs.data_json, je.attempt_index\n ", + "query": "\n WITH selected_jobs AS (\n SELECT je.id, je.execution_state_json AS data_json\n FROM job_executions je\n JOIN jobs ON je.id = jobs.id\n WHERE reschedule_after < $2::timestamptz\n AND je.state = 'pending'\n ORDER BY reschedule_after ASC\n LIMIT $1\n FOR UPDATE\n )\n UPDATE job_executions AS je\n SET state = 'running', reschedule_after = $2::timestamptz + $3::interval\n FROM selected_jobs\n WHERE je.id = selected_jobs.id\n RETURNING je.id AS \"id!: JobId\", selected_jobs.data_json, je.attempt_index\n ", "describe": { "columns": [ { @@ -32,5 +32,5 @@ false ] }, - "hash": "96435b2b5714e99f2055584854a19f6aa0bbb43ebb0ede7c506d36a38b94600c" + "hash": "5501335ba40775766d8425f09a4096d94594d0ed0e9064047c7bcc042fdd609d" } diff --git a/lana/dashboard/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/lana/dashboard/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/lana/dashboard/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/lana/dashboard/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json b/lana/dashboard/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json deleted file mode 100644 index ef54cdb3b..000000000 --- a/lana/dashboard/.sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v0 is NULL OR v0 = COALESCE($2,v0)) AND\n (v1 is NULL OR v1 = COALESCE($3,v1)) AND\n (v2 is NULL OR v2 = COALESCE($4,v2)) AND\n (v3 is NULL OR v3 = COALESCE($5,v3)) AND\n (v4 is NULL OR v4 = COALESCE($6,v4)) AND\n (v5 is NULL OR v5 = COALESCE($7,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119" -} diff --git a/lana/dashboard/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json b/lana/dashboard/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json deleted file mode 100644 index 0daaa8a87..000000000 --- a/lana/dashboard/.sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v2 is NULL OR v2 = COALESCE($2,v2)) AND\n (v3 is NULL OR v3 = COALESCE($3,v3)) AND\n (v4 is NULL OR v4 = COALESCE($4,v4)) AND\n (v5 is NULL OR v5 = COALESCE($5,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar", - "Varchar", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b" -} diff --git a/lana/dashboard/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json b/lana/dashboard/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json deleted file mode 100644 index 4a5f7e808..000000000 --- a/lana/dashboard/.sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "DELETE FROM casbin_rule WHERE\n ptype = $1 AND\n (v5 is NULL OR v5 = COALESCE($2,v5))", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Varchar" - ] - }, - "nullable": [] - }, - "hash": "fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b" -} diff --git a/lana/dashboard/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json b/lana/dashboard/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json deleted file mode 100644 index 897ae5268..000000000 --- a/lana/dashboard/.sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * from casbin_rule WHERE (\n ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )\n OR (\n ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "ptype", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "v0", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "v1", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "v2", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "v3", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "v4", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "v5", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false - ] - }, - "hash": "fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345" -} diff --git a/lib/audit/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/lib/audit/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/lib/audit/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/lib/authz/Cargo.toml b/lib/authz/Cargo.toml index 243e5e6d3..730a64b78 100644 --- a/lib/authz/Cargo.toml +++ b/lib/authz/Cargo.toml @@ -6,10 +6,13 @@ edition = "2021" [features] fail-on-warnings = [] +test-dummy = [ "dep:es-entity" ] [dependencies] audit = { path = "../audit" } +es-entity = { workspace = true, optional = true } + sqlx-adapter = { version = "1.6.0", default-features = false, features = ["postgres", "runtime-tokio-rustls"]} async-trait = { workspace = true } diff --git a/lib/authz/src/dummy.rs b/lib/authz/src/dummy.rs new file mode 100644 index 000000000..8b534d2aa --- /dev/null +++ b/lib/authz/src/dummy.rs @@ -0,0 +1,166 @@ +use async_trait::async_trait; + +use std::fmt; + +use audit::{error::AuditError, AuditCursor, AuditEntry, AuditInfo, AuditSvc}; + +use crate::{error::AuthorizationError, PermissionCheck}; + +#[derive(Clone)] +pub struct DummyAudit { + _phantom: std::marker::PhantomData<(A, O)>, +} +#[derive(Clone)] +pub struct DummyPerms { + audit: DummyAudit, +} +impl DummyPerms { + pub fn new() -> Self { + Self { + audit: DummyAudit { + _phantom: std::marker::PhantomData, + }, + } + } +} + +impl Default for DummyPerms { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug, Clone, Copy)] +pub struct DummySubject; +impl audit::SystemSubject for DummySubject { + fn system() -> Self { + DummySubject + } +} + +impl fmt::Display for DummySubject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "item") + } +} + +impl std::str::FromStr for DummySubject { + type Err = std::convert::Infallible; + + fn from_str(_: &str) -> Result { + Ok(DummySubject) + } +} + +#[async_trait] +impl AuditSvc for DummyAudit +where + A: std::str::FromStr + std::fmt::Display + std::fmt::Debug + Copy + Send + Sync, + O: std::str::FromStr + std::fmt::Display + std::fmt::Debug + Copy + Send + Sync, +{ + type Subject = DummySubject; + type Object = O; + type Action = A; + + fn pool(&self) -> &sqlx::PgPool { + unimplemented!() + } + + async fn record_system_entry( + &self, + _object: impl Into + Send, + _action: impl Into + Send, + ) -> Result { + Ok(dummy_audit_info()) + } + + async fn record_entry( + &self, + _subject: &Self::Subject, + _object: impl Into + Send, + _action: impl Into + Send, + _authorized: bool, + ) -> Result { + Ok(dummy_audit_info()) + } + + async fn record_system_entry_in_tx( + &self, + _tx: &mut sqlx::Transaction<'_, sqlx::Postgres>, + _object: impl Into + Send, + _action: impl Into + Send, + ) -> Result { + Ok(dummy_audit_info()) + } + + async fn record_entry_in_tx( + &self, + _tx: &mut sqlx::Transaction<'_, sqlx::Postgres>, + _subject: &Self::Subject, + _object: impl Into + Send, + _action: impl Into + Send, + _authorized: bool, + ) -> Result { + Ok(dummy_audit_info()) + } + + async fn list( + &self, + _query: es_entity::PaginatedQueryArgs, + ) -> Result< + es_entity::PaginatedQueryRet< + AuditEntry, + AuditCursor, + >, + AuditError, + > { + Ok(es_entity::PaginatedQueryRet { + entities: vec![], + has_next_page: false, + end_cursor: None, + }) + } +} + +fn dummy_audit_info() -> audit::AuditInfo { + AuditInfo { + audit_entry_id: audit::AuditEntryId::from(1), + sub: "sub".to_string(), + } +} + +#[async_trait] +impl PermissionCheck for DummyPerms +where + A: std::str::FromStr + std::fmt::Display + std::fmt::Debug + Copy + Clone + Send + Sync, + O: std::str::FromStr + std::fmt::Display + std::fmt::Debug + Copy + Clone + Send + Sync, +{ + type Audit = DummyAudit; + + fn audit(&self) -> &Self::Audit { + &self.audit + } + + async fn enforce_permission( + &self, + _sub: &::Subject, + _object: impl Into<::Object> + std::fmt::Debug + Send, + _action: impl Into<::Action> + std::fmt::Debug + Send, + ) -> Result { + Ok(dummy_audit_info()) + } + + async fn evaluate_permission( + &self, + _sub: &::Subject, + _object: impl Into<::Object> + std::fmt::Debug + Send, + _action: impl Into<::Action> + std::fmt::Debug + Send, + enforce: bool, + ) -> Result, AuthorizationError> { + if enforce { + Ok(Some(dummy_audit_info())) + } else { + Ok(None) + } + } +} diff --git a/lib/authz/src/lib.rs b/lib/authz/src/lib.rs index a3a5d3e8f..fe88e4b11 100644 --- a/lib/authz/src/lib.rs +++ b/lib/authz/src/lib.rs @@ -1,5 +1,7 @@ mod all_or_one; mod check_trait; +#[cfg(feature = "test-dummy")] +pub mod dummy; pub mod error; use async_trait::async_trait; diff --git a/lib/job/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/lib/job/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/lib/job/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/lib/outbox/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json b/lib/outbox/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json deleted file mode 100644 index 60f58c60f..000000000 --- a/lib/outbox/.sqlx/query-6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT NOW()", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "now", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "6bae2f6ec3f8d5295b935cef18cb3dd649758b5afcf70feb2a6eff7d69925bfc" -} diff --git a/lib/outbox/src/event.rs b/lib/outbox/src/event.rs index 3c0bfb30c..a50876fbd 100644 --- a/lib/outbox/src/event.rs +++ b/lib/outbox/src/event.rs @@ -9,6 +9,14 @@ pub trait OutboxEventMarker: { fn as_event(&self) -> Option<&E>; } +impl OutboxEventMarker for T +where + T: serde::de::DeserializeOwned + serde::Serialize + Send + Sync + 'static + Unpin + From, +{ + fn as_event(&self) -> Option<&T> { + Some(self) + } +} pub enum OutboxEvent

where