From a81bfe28edd7fc543af19b9546cbe30492716c97 Mon Sep 17 00:00:00 2001 From: Hrithikesh <61539176+hrithikesh026@users.noreply.github.com> Date: Mon, 11 Sep 2023 23:09:36 +0530 Subject: [PATCH] feat(core): enable payments void for multiple partial capture (#2048) --- Cargo.lock | 692 ++---------------- crates/common_enums/src/enums.rs | 30 + .../src/payments/payment_attempt.rs | 8 + crates/diesel_models/src/payment_attempt.rs | 21 + crates/diesel_models/src/schema.rs | 1 + crates/router/src/core/payments.rs | 1 + crates/router/src/core/payments/helpers.rs | 1 + .../payments/operations/payment_capture.rs | 20 +- .../payments/operations/payment_response.rs | 55 +- .../router/src/core/payments/transformers.rs | 5 +- .../src/types/storage/payment_attempt.rs | 14 +- .../src/mock_db/payment_attempt.rs | 1 + .../src/payments/payment_attempt.rs | 27 + .../down.sql | 3 + .../up.sql | 3 + 15 files changed, 230 insertions(+), 652 deletions(-) create mode 100644 migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/down.sql create mode 100644 migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/up.sql diff --git a/Cargo.lock b/Cargo.lock index 092a1018cc..50e5e015a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,12 +297,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - [[package]] name = "ahash" version = "0.7.6" @@ -385,14 +379,15 @@ dependencies = [ "cards", "common_enums", "common_utils", - "error-stack", + "frunk", + "frunk_core", "masking", "mime", "reqwest", "router_derive", "serde", "serde_json", - "strum 0.24.1", + "strum", "time 0.3.22", "url", "utoipa", @@ -422,45 +417,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c" -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time 0.3.22", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "assert-json-diff" version = "2.0.2" @@ -471,18 +427,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-bb8-diesel" -version = "0.1.0" -source = "git+https://github.com/juspay/async-bb8-diesel?rev=9a71d142726dbc33f41c1fd935ddaa79841c7be5#9a71d142726dbc33f41c1fd935ddaa79841c7be5" -dependencies = [ - "async-trait", - "bb8", - "diesel", - "thiserror", - "tokio", -] - [[package]] name = "async-bb8-diesel" version = "0.1.0" @@ -497,9 +441,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ "concurrent-queue", "event-listener", @@ -567,18 +511,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -735,39 +679,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "aws-sdk-s3" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "392b9811ca489747ac84349790e49deaa1f16631949e7dd4156000251c260eae" -dependencies = [ - "aws-credential-types", - "aws-endpoint", - "aws-http", - "aws-sig-auth", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-checksums", - "aws-smithy-client", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-http-tower", - "aws-smithy-json", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "bytes", - "http", - "http-body", - "once_cell", - "percent-encoding", - "regex", - "tokio-stream", - "tower", - "tracing", - "url", -] - [[package]] name = "aws-sdk-s3" version = "0.28.0" @@ -1249,12 +1160,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" -[[package]] -name = "bytemuck" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" - [[package]] name = "byteorder" version = "1.4.3" @@ -1371,12 +1276,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "chrono" version = "0.4.26" @@ -1424,7 +1323,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -1433,23 +1332,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "common_enums" version = "0.1.0" dependencies = [ - "common_utils", "diesel", "router_derive", "serde", "serde_json", - "strum 0.25.0", - "time 0.3.22", + "strum", "utoipa", ] @@ -1602,17 +1493,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - [[package]] name = "crossbeam-epoch" version = "0.9.15" @@ -1690,7 +1570,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -1712,7 +1592,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core 0.20.1", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -1728,29 +1608,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "data-encoding" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" - -[[package]] -name = "data_models" -version = "0.1.0" -dependencies = [ - "api_models", - "async-trait", - "common_enums", - "common_utils", - "error-stack", - "masking", - "serde", - "serde_json", - "strum 0.25.0", - "thiserror", - "time 0.3.22", -] - [[package]] name = "deadpool" version = "0.9.5" @@ -1770,30 +1627,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaa37046cc0f6c3cc6090fbdbf73ef0b8ef4cfcc37f6befc0020f63e8cf121e1" -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "derive_deref" version = "1.1.1" @@ -1843,31 +1676,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.29", -] - -[[package]] -name = "diesel_models" -version = "0.1.0" -dependencies = [ - "async-bb8-diesel 0.1.0 (git+https://github.com/oxidecomputer/async-bb8-diesel?rev=be3d9bce50051d8c0e0c06078e8066cc27db3001)", - "aws-config", - "aws-sdk-s3 0.28.0", - "common_enums", - "common_utils", - "diesel", - "error-stack", - "external_services", - "frunk", - "frunk_core", - "masking", - "router_derive", - "router_env", - "serde", - "serde_json", - "strum 0.24.1", - "thiserror", - "time 0.3.22", + "syn 2.0.18", ] [[package]] @@ -1876,7 +1685,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -1916,17 +1725,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", -] - [[package]] name = "dlv-list" version = "0.3.0" @@ -1937,31 +1735,30 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" name = "drainer" version = "0.1.0" dependencies = [ - "async-bb8-diesel 0.1.0 (git+https://github.com/oxidecomputer/async-bb8-diesel?rev=be3d9bce50051d8c0e0c06078e8066cc27db3001)", + "async-bb8-diesel", "bb8", "clap", "common_utils", "config", "diesel", - "diesel_models", "error-stack", "external_services", - "masking", "once_cell", "redis_interface", "router_env", "serde", "serde_json", "serde_path_to_error", + "storage_models", "thiserror", "tokio", ] [[package]] name = "dyn-clone" -version = "1.0.13" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "either" @@ -1985,20 +1782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" -dependencies = [ - "humantime 2.1.0", - "is-terminal", + "humantime", "log", "regex", "termcolor", @@ -2080,9 +1864,9 @@ dependencies = [ [[package]] name = "fake" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af7b0c58ac9d03169e27f080616ce9f64004edca3d2ef4147a811c21b23b319" +checksum = "0a44c765350db469b774425ff1c833890b16ceb9612fb5d7c4bbdf4a1b55f876" dependencies = [ "rand 0.8.5", "unidecode", @@ -2126,7 +1910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2333,7 +2117,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -2414,16 +2198,6 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "gif" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "git2" version = "0.17.2" @@ -2586,17 +2360,11 @@ dependencies = [ "quick-error", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -2695,25 +2463,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "image" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "gif", - "jpeg-decoder", - "num-iter", - "num-rational", - "num-traits", - "png", - "scoped_threadpool", - "tiff", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -2776,18 +2525,6 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -2830,15 +2567,6 @@ dependencies = [ "time 0.3.22", ] -[[package]] -name = "jpeg-decoder" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" -dependencies = [ - "rayon", -] - [[package]] name = "js-sys" version = "0.3.64" @@ -3122,25 +2850,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -3164,9 +2873,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.11.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "206bf83f415b0579fd885fe0804eb828e727636657dc1bf73d80d2f1218e14a1" dependencies = [ "async-io", "async-lock", @@ -3255,28 +2964,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -3297,15 +2984,6 @@ dependencies = [ "libc", ] -[[package]] -name = "oid-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" -dependencies = [ - "asn1-rs", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -3341,7 +3019,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -3555,7 +3233,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -3606,7 +3284,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -3627,18 +3305,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "png" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "deflate", - "miniz_oxide 0.3.7", -] - [[package]] name = "polling" version = "2.8.0" @@ -3676,7 +3342,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" dependencies = [ - "env_logger 0.7.1", + "env_logger", "log", ] @@ -3712,9 +3378,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] @@ -3773,16 +3439,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "qrcode" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" -dependencies = [ - "checked_int_cast", - "image", -] - [[package]] name = "quanta" version = "0.11.1" @@ -3817,9 +3473,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -3924,28 +3580,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - [[package]] name = "redis-protocol" version = "4.1.0" @@ -4130,11 +3764,11 @@ dependencies = [ "actix-rt", "actix-web", "api_models", - "async-bb8-diesel 0.1.0 (git+https://github.com/oxidecomputer/async-bb8-diesel?rev=be3d9bce50051d8c0e0c06078e8066cc27db3001)", + "async-bb8-diesel", "async-trait", "awc", "aws-config", - "aws-sdk-s3 0.28.0", + "aws-sdk-s3", "base64 0.21.2", "bb8", "blake3", @@ -4143,19 +3777,18 @@ dependencies = [ "clap", "common_utils", "config", - "data_models", + "crc32fast", "derive_deref", "diesel", - "diesel_models", "dyn-clone", "encoding_rs", "error-stack", "external_services", + "frunk", + "frunk_core", "futures", "hex", "http", - "hyper", - "image", "infer 0.13.0", "josekit", "jsonwebtoken", @@ -4164,11 +3797,10 @@ dependencies = [ "maud", "mimalloc", "mime", + "moka", "nanoid", "num_cpus", "once_cell", - "openssl", - "qrcode", "rand 0.8.5", "redis_interface", "regex", @@ -4176,8 +3808,6 @@ dependencies = [ "ring", "router_derive", "router_env", - "roxmltree", - "scheduler", "serde", "serde_json", "serde_path_to_error", @@ -4187,8 +3817,8 @@ dependencies = [ "serial_test", "signal-hook", "signal-hook-tokio", - "storage_impl", - "strum 0.24.1", + "storage_models", + "strum", "test_utils", "thirtyfour", "thiserror", @@ -4200,7 +3830,6 @@ dependencies = [ "utoipa-swagger-ui", "uuid", "wiremock", - "x509-parser", ] [[package]] @@ -4214,7 +3843,7 @@ dependencies = [ "quote", "serde", "serde_json", - "strum 0.24.1", + "strum", "syn 1.0.109", ] @@ -4232,7 +3861,7 @@ dependencies = [ "serde", "serde_json", "serde_path_to_error", - "strum 0.24.1", + "strum", "time 0.3.22", "tokio", "tracing", @@ -4244,15 +3873,6 @@ dependencies = [ "vergen", ] -[[package]] -name = "roxmltree" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f595a457b6b8c6cda66a48503e92ee8d19342f905948f29c383200ec9eb1d8" -dependencies = [ - "xmlparser", -] - [[package]] name = "rust-embed" version = "6.7.0" @@ -4274,7 +3894,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.29", + "syn 2.0.18", "walkdir", ] @@ -4313,15 +3933,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - [[package]] name = "rustix" version = "0.37.20" @@ -4420,55 +4031,6 @@ dependencies = [ "parking_lot", ] -[[package]] -name = "scheduler" -version = "0.1.0" -dependencies = [ - "actix-multipart", - "actix-rt", - "actix-web", - "api_models", - "async-bb8-diesel 0.1.0 (git+https://github.com/juspay/async-bb8-diesel?rev=9a71d142726dbc33f41c1fd935ddaa79841c7be5)", - "async-trait", - "aws-config", - "aws-sdk-s3 0.25.1", - "cards", - "clap", - "common_utils", - "diesel", - "diesel_models", - "dyn-clone", - "env_logger 0.10.0", - "error-stack", - "external_services", - "frunk", - "frunk_core", - "futures", - "infer 0.13.0", - "masking", - "once_cell", - "rand 0.8.5", - "redis_interface", - "router_derive", - "router_env", - "serde", - "serde_json", - "signal-hook", - "signal-hook-tokio", - "storage_impl", - "strum 0.24.1", - "thiserror", - "time 0.3.22", - "tokio", - "uuid", -] - -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" version = "1.1.0" @@ -4519,31 +4081,31 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ - "indexmap 2.0.0", + "indexmap 1.9.3", "itoa", "ryu", "serde", @@ -4597,7 +4159,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -4646,7 +4208,7 @@ dependencies = [ "darling 0.20.1", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -4671,7 +4233,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -4815,37 +4377,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "storage_impl" +name = "storage_models" version = "0.1.0" dependencies = [ - "actix-web", - "api_models", - "async-bb8-diesel 0.1.0 (git+https://github.com/oxidecomputer/async-bb8-diesel?rev=be3d9bce50051d8c0e0c06078e8066cc27db3001)", - "async-trait", - "bb8", - "bytes", + "async-bb8-diesel", + "common_enums", "common_utils", - "config", - "crc32fast", - "data_models", "diesel", - "diesel_models", - "dyn-clone", "error-stack", - "external_services", - "futures", - "http", + "frunk", + "frunk_core", "masking", - "mime", - "moka", - "once_cell", - "redis_interface", - "ring", + "router_derive", "router_env", "serde", "serde_json", + "strum", "thiserror", - "tokio", + "time 0.3.22", ] [[package]] @@ -4869,16 +4418,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros 0.24.3", -] - -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" -dependencies = [ - "strum_macros 0.25.2", + "strum_macros", ] [[package]] @@ -4894,19 +4434,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum_macros" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.29", -] - [[package]] name = "subtle" version = "2.4.1" @@ -4926,9 +4453,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -4941,18 +4468,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "tagptr" version = "0.2.0" @@ -5021,27 +4536,14 @@ dependencies = [ name = "test_utils" version = "0.1.0" dependencies = [ - "actix-http", - "actix-web", "api_models", - "async-trait", - "awc", - "base64 0.21.2", "clap", - "derive_deref", "masking", - "rand 0.8.5", - "reqwest", + "router", "serde", "serde_json", "serde_path_to_error", - "serde_urlencoded", - "serial_test", - "thirtyfour", - "time 0.3.22", - "tokio", "toml 0.7.4", - "uuid", ] [[package]] @@ -5099,7 +4601,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -5112,17 +4614,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" -dependencies = [ - "jpeg-decoder", - "miniz_oxide 0.4.4", - "weezl", -] - [[package]] name = "time" version = "0.1.45" @@ -5213,7 +4704,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -5560,12 +5051,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "unidecode" version = "0.3.0" @@ -5623,7 +5108,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", ] [[package]] @@ -5762,7 +5247,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", "wasm-bindgen-shared", ] @@ -5796,7 +5281,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5838,9 +5323,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.22.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", "untrusted", @@ -5855,12 +5340,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - [[package]] name = "winapi" version = "0.3.9" @@ -6064,23 +5543,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "x509-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror", - "time 0.3.22", -] - [[package]] name = "xmlparser" version = "0.13.5" diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index d1e3a7c6b2..27b43844f0 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -59,6 +59,36 @@ pub enum AttemptStatus { DeviceDataCollectionPending, } +impl AttemptStatus { + pub fn is_terminal_status(self) -> bool { + match self { + Self::RouterDeclined + | Self::Charged + | Self::AutoRefunded + | Self::Voided + | Self::VoidFailed + | Self::CaptureFailed + | Self::Failure => true, + Self::Started + | Self::AuthenticationFailed + | Self::AuthenticationPending + | Self::AuthenticationSuccessful + | Self::Authorized + | Self::AuthorizationFailed + | Self::Authorizing + | Self::CodInitiated + | Self::VoidInitiated + | Self::CaptureInitiated + | Self::PartialCharged + | Self::Unresolved + | Self::Pending + | Self::PaymentMethodAwaited + | Self::ConfirmationAwaited + | Self::DeviceDataCollectionPending => false, + } + } +} + #[derive( Clone, Copy, diff --git a/crates/data_models/src/payments/payment_attempt.rs b/crates/data_models/src/payments/payment_attempt.rs index 68e083abd1..1538452e5a 100644 --- a/crates/data_models/src/payments/payment_attempt.rs +++ b/crates/data_models/src/payments/payment_attempt.rs @@ -137,6 +137,7 @@ pub struct PaymentAttempt { pub multiple_capture_count: Option, // reference to the payment at connector side pub connector_response_reference_id: Option, + pub amount_capturable: i64, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -192,6 +193,7 @@ pub struct PaymentAttemptNew { pub error_reason: Option, pub connector_response_reference_id: Option, pub multiple_capture_count: Option, + pub amount_capturable: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -257,6 +259,7 @@ pub enum PaymentAttemptUpdate { error_message: Option>, error_reason: Option>, connector_response_reference_id: Option, + amount_capturable: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, @@ -277,10 +280,15 @@ pub enum PaymentAttemptUpdate { error_code: Option>, error_message: Option>, error_reason: Option>, + amount_capturable: Option, }, MultipleCaptureCountUpdate { multiple_capture_count: i16, }, + AmountToCaptureUpdate { + status: storage_enums::AttemptStatus, + amount_capturable: i64, + }, PreprocessingUpdate { status: storage_enums::AttemptStatus, payment_method_id: Option>, diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 9cb025c52b..dac9977d22 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -56,6 +56,7 @@ pub struct PaymentAttempt { pub multiple_capture_count: Option, // reference to the payment at connector side pub connector_response_reference_id: Option, + pub amount_capturable: i64, } #[derive(Clone, Debug, Eq, PartialEq, Queryable, Serialize, Deserialize)] @@ -113,6 +114,7 @@ pub struct PaymentAttemptNew { pub error_reason: Option, pub connector_response_reference_id: Option, pub multiple_capture_count: Option, + pub amount_capturable: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -178,6 +180,7 @@ pub enum PaymentAttemptUpdate { error_message: Option>, error_reason: Option>, connector_response_reference_id: Option, + amount_capturable: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, @@ -198,10 +201,15 @@ pub enum PaymentAttemptUpdate { error_code: Option>, error_message: Option>, error_reason: Option>, + amount_capturable: Option, }, MultipleCaptureCountUpdate { multiple_capture_count: i16, }, + AmountToCaptureUpdate { + status: storage_enums::AttemptStatus, + amount_capturable: i64, + }, PreprocessingUpdate { status: storage_enums::AttemptStatus, payment_method_id: Option>, @@ -242,6 +250,7 @@ pub struct PaymentAttemptUpdateInternal { capture_method: Option, connector_response_reference_id: Option, multiple_capture_count: Option, + amount_capturable: Option, } impl PaymentAttemptUpdate { @@ -380,6 +389,7 @@ impl From for PaymentAttemptUpdateInternal { error_message, error_reason, connector_response_reference_id, + amount_capturable, } => Self { status: Some(status), connector, @@ -394,6 +404,7 @@ impl From for PaymentAttemptUpdateInternal { payment_token, error_reason, connector_response_reference_id, + amount_capturable, ..Default::default() }, PaymentAttemptUpdate::ErrorUpdate { @@ -402,6 +413,7 @@ impl From for PaymentAttemptUpdateInternal { error_code, error_message, error_reason, + amount_capturable, } => Self { connector, status: Some(status), @@ -409,6 +421,7 @@ impl From for PaymentAttemptUpdateInternal { error_code, modified_at: Some(common_utils::date_time::now()), error_reason, + amount_capturable, ..Default::default() }, PaymentAttemptUpdate::StatusUpdate { status } => Self { @@ -469,6 +482,14 @@ impl From for PaymentAttemptUpdateInternal { multiple_capture_count: Some(multiple_capture_count), ..Default::default() }, + PaymentAttemptUpdate::AmountToCaptureUpdate { + status, + amount_capturable, + } => Self { + status: Some(status), + amount_capturable: Some(amount_capturable), + ..Default::default() + }, } } } diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index f6c2bed8ab..2237f466c1 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -545,6 +545,7 @@ diesel::table! { multiple_capture_count -> Nullable, #[max_length = 128] connector_response_reference_id -> Nullable, + amount_capturable -> Int8, } } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index a47f52c65a..0074c045e2 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1483,6 +1483,7 @@ pub fn should_call_connector( "PaymentCancel" => matches!( payment_data.payment_intent.status, storage_enums::IntentStatus::RequiresCapture + | storage_enums::IntentStatus::PartiallyCaptured ), "PaymentCapture" => { matches!( diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 549f0d548c..892f8fe239 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2696,6 +2696,7 @@ impl AttemptType { error_reason: None, multiple_capture_count: None, connector_response_reference_id: None, + amount_capturable: old_payment_attempt.amount, } } diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index b2f1c5bd25..596e25f052 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -91,6 +91,12 @@ impl GetTracker, api::PaymentsCaptu let amount_to_capture = request .amount_to_capture .get_required_value("amount_to_capture")?; + + helpers::validate_amount_to_capture( + payment_attempt.amount_capturable, + Some(amount_to_capture), + )?; + let previous_captures = db .find_all_captures_by_merchant_id_payment_id_authorized_attempt_id( &payment_attempt.merchant_id, @@ -100,20 +106,6 @@ impl GetTracker, api::PaymentsCaptu ) .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - let previously_blocked_amount = - previous_captures.iter().fold(0, |accumulator, capture| { - accumulator - + match capture.status { - enums::CaptureStatus::Charged | enums::CaptureStatus::Pending => { - capture.amount - } - enums::CaptureStatus::Started | enums::CaptureStatus::Failed => 0, - } - }); - helpers::validate_amount_to_capture( - payment_attempt.amount - previously_blocked_amount, - Some(amount_to_capture), - )?; let capture = db .insert_capture( diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 4fe23c0f4b..fc0b9c1dab 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -17,8 +17,8 @@ use crate::{ services::RedirectForm, types::{ self, api, - storage::{self, enums}, - transformers::{ForeignFrom, ForeignTryFrom}, + storage::{self, enums, payment_attempt::PaymentAttemptExt}, + transformers::ForeignTryFrom, CaptureSyncResponse, }, utils, @@ -305,19 +305,27 @@ async fn payment_response_update_tracker( )]; (Some((multiple_capture_data, capture_update_list)), None) } - None => ( - None, - Some(storage::PaymentAttemptUpdate::ErrorUpdate { - connector: None, - status: match err.status_code { - 500..=511 => storage::enums::AttemptStatus::Pending, - _ => storage::enums::AttemptStatus::Failure, - }, - error_message: Some(Some(err.message)), - error_code: Some(Some(err.code)), - error_reason: Some(err.reason), - }), - ), + None => { + let status = match err.status_code { + 500..=511 => storage::enums::AttemptStatus::Pending, + _ => storage::enums::AttemptStatus::Failure, + }; + ( + None, + Some(storage::PaymentAttemptUpdate::ErrorUpdate { + connector: None, + status, + error_message: Some(Some(err.message)), + error_code: Some(Some(err.code)), + error_reason: Some(err.reason), + amount_capturable: if status.is_terminal_status() { + Some(0) + } else { + None + }, + }), + ) + } }; ( capture_update, @@ -422,6 +430,11 @@ async fn payment_response_update_tracker( error_message: error_status.clone(), error_reason: error_status, connector_response_reference_id, + amount_capturable: if router_data.status.is_terminal_status() { + Some(0) + } else { + None + }, }), ), }; @@ -499,8 +512,10 @@ async fn payment_response_update_tracker( let authorized_amount = payment_data.payment_attempt.amount; - payment_attempt_update = Some(storage::PaymentAttemptUpdate::StatusUpdate { + payment_attempt_update = Some(storage::PaymentAttemptUpdate::AmountToCaptureUpdate { status: multiple_capture_data.get_attempt_status(authorized_amount), + amount_capturable: payment_data.payment_attempt.amount + - multiple_capture_data.get_total_blocked_amount(), }); Some(multiple_capture_data) } @@ -553,10 +568,14 @@ async fn payment_response_update_tracker( ); let payment_intent_update = match &router_data.response { Err(_) => storage::PaymentIntentUpdate::PGStatusUpdate { - status: enums::IntentStatus::foreign_from(payment_data.payment_attempt.status), + status: payment_data + .payment_attempt + .get_intent_status(payment_data.payment_intent.amount_captured), }, Ok(_) => storage::PaymentIntentUpdate::ResponseUpdate { - status: enums::IntentStatus::foreign_from(payment_data.payment_attempt.status), + status: payment_data + .payment_attempt + .get_intent_status(payment_data.payment_intent.amount_captured), return_url: router_data.return_url.clone(), amount_captured, }, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 25c9fb2c84..6da9ef5707 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -519,16 +519,13 @@ where connector_name, ) }); - - let amount_captured = payment_intent.amount_captured.unwrap_or_default(); - let amount_capturable = Some(payment_attempt.amount - amount_captured); services::ApplicationResponse::JsonWithHeaders(( response .set_payment_id(Some(payment_attempt.payment_id)) .set_merchant_id(Some(payment_attempt.merchant_id)) .set_status(payment_intent.status) .set_amount(payment_attempt.amount) - .set_amount_capturable(amount_capturable) + .set_amount_capturable(Some(payment_attempt.amount_capturable)) .set_amount_received(payment_intent.amount_captured) .set_connector(routed_through) .set_client_secret(payment_intent.client_secret.map(masking::Secret::new)) diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs index 1a9af97329..8b78be195a 100644 --- a/crates/router/src/types/storage/payment_attempt.rs +++ b/crates/router/src/types/storage/payment_attempt.rs @@ -4,7 +4,9 @@ pub use data_models::payments::payment_attempt::{ use diesel_models::{capture::CaptureNew, enums}; use error_stack::ResultExt; -use crate::{core::errors, errors::RouterResult, utils::OptionExt}; +use crate::{ + core::errors, errors::RouterResult, types::transformers::ForeignFrom, utils::OptionExt, +}; pub trait PaymentAttemptExt { fn make_new_capture( @@ -14,6 +16,7 @@ pub trait PaymentAttemptExt { ) -> RouterResult; fn get_next_capture_id(&self) -> String; + fn get_intent_status(&self, amount_captured: Option) -> enums::IntentStatus; } impl PaymentAttemptExt for PaymentAttempt { @@ -55,6 +58,15 @@ impl PaymentAttemptExt for PaymentAttempt { let next_sequence_number = self.multiple_capture_count.unwrap_or_default() + 1; format!("{}_{}", self.attempt_id.clone(), next_sequence_number) } + + fn get_intent_status(&self, amount_captured: Option) -> enums::IntentStatus { + let intent_status = enums::IntentStatus::foreign_from(self.status); + if intent_status == enums::IntentStatus::Cancelled && amount_captured > Some(0) { + enums::IntentStatus::Succeeded + } else { + intent_status + } + } } #[cfg(test)] diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs index 32b33d5967..b4f6e1cdf1 100644 --- a/crates/storage_impl/src/mock_db/payment_attempt.rs +++ b/crates/storage_impl/src/mock_db/payment_attempt.rs @@ -137,6 +137,7 @@ impl PaymentAttemptInterface for MockDb { error_reason: payment_attempt.error_reason, multiple_capture_count: payment_attempt.multiple_capture_count, connector_response_reference_id: None, + amount_capturable: payment_attempt.amount_capturable, }; payment_attempts.push(payment_attempt.clone()); Ok(payment_attempt) diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index c2a5a97da1..332dc3f8dc 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -341,6 +341,7 @@ impl PaymentAttemptInterface for KVRouterStore { error_reason: payment_attempt.error_reason.clone(), multiple_capture_count: payment_attempt.multiple_capture_count, connector_response_reference_id: None, + amount_capturable: payment_attempt.amount_capturable, }; let field = format!("pa_{}", created_attempt.attempt_id); @@ -905,6 +906,7 @@ impl DataModelExt for PaymentAttempt { error_reason: self.error_reason, multiple_capture_count: self.multiple_capture_count, connector_response_reference_id: self.connector_response_reference_id, + amount_capturable: self.amount_capturable, } } @@ -952,6 +954,7 @@ impl DataModelExt for PaymentAttempt { error_reason: storage_model.error_reason, multiple_capture_count: storage_model.multiple_capture_count, connector_response_reference_id: storage_model.connector_response_reference_id, + amount_capturable: storage_model.amount_capturable, } } } @@ -999,6 +1002,7 @@ impl DataModelExt for PaymentAttemptNew { error_reason: self.error_reason, connector_response_reference_id: self.connector_response_reference_id, multiple_capture_count: self.multiple_capture_count, + amount_capturable: self.amount_capturable, } } @@ -1044,6 +1048,7 @@ impl DataModelExt for PaymentAttemptNew { error_reason: storage_model.error_reason, connector_response_reference_id: storage_model.connector_response_reference_id, multiple_capture_count: storage_model.multiple_capture_count, + amount_capturable: storage_model.amount_capturable, } } } @@ -1147,6 +1152,7 @@ impl DataModelExt for PaymentAttemptUpdate { error_message, error_reason, connector_response_reference_id, + amount_capturable, } => DieselPaymentAttemptUpdate::ResponseUpdate { status, connector, @@ -1160,6 +1166,7 @@ impl DataModelExt for PaymentAttemptUpdate { error_message, error_reason, connector_response_reference_id, + amount_capturable, }, Self::UnresolvedResponseUpdate { status, @@ -1187,12 +1194,14 @@ impl DataModelExt for PaymentAttemptUpdate { error_code, error_message, error_reason, + amount_capturable, } => DieselPaymentAttemptUpdate::ErrorUpdate { connector, status, error_code, error_message, error_reason, + amount_capturable, }, Self::MultipleCaptureCountUpdate { multiple_capture_count, @@ -1223,6 +1232,13 @@ impl DataModelExt for PaymentAttemptUpdate { error_code, error_message, }, + Self::AmountToCaptureUpdate { + status, + amount_capturable, + } => DieselPaymentAttemptUpdate::AmountToCaptureUpdate { + status, + amount_capturable, + }, } } @@ -1322,6 +1338,7 @@ impl DataModelExt for PaymentAttemptUpdate { error_message, error_reason, connector_response_reference_id, + amount_capturable, } => Self::ResponseUpdate { status, connector, @@ -1335,6 +1352,7 @@ impl DataModelExt for PaymentAttemptUpdate { error_message, error_reason, connector_response_reference_id, + amount_capturable, }, DieselPaymentAttemptUpdate::UnresolvedResponseUpdate { status, @@ -1362,12 +1380,14 @@ impl DataModelExt for PaymentAttemptUpdate { error_code, error_message, error_reason, + amount_capturable, } => Self::ErrorUpdate { connector, status, error_code, error_message, error_reason, + amount_capturable, }, DieselPaymentAttemptUpdate::MultipleCaptureCountUpdate { multiple_capture_count, @@ -1398,6 +1418,13 @@ impl DataModelExt for PaymentAttemptUpdate { error_code, error_message, }, + DieselPaymentAttemptUpdate::AmountToCaptureUpdate { + status, + amount_capturable, + } => Self::AmountToCaptureUpdate { + status, + amount_capturable, + }, } } } diff --git a/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/down.sql b/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/down.sql new file mode 100644 index 0000000000..a1e62c1c6d --- /dev/null +++ b/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE payment_attempt +DROP COLUMN amount_capturable; \ No newline at end of file diff --git a/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/up.sql b/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/up.sql new file mode 100644 index 0000000000..271b072d6b --- /dev/null +++ b/migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE payment_attempt +ADD COLUMN IF NOT EXISTS amount_capturable BIGINT NOT NULL DEFAULT 0; \ No newline at end of file