diff --git a/crates/openapi/src/routes/disputes.rs b/crates/openapi/src/routes/disputes.rs index 491edae410..c5875d67a9 100644 --- a/crates/openapi/src/routes/disputes.rs +++ b/crates/openapi/src/routes/disputes.rs @@ -42,3 +42,30 @@ pub async fn retrieve_dispute() {} security(("api_key" = [])) )] pub async fn retrieve_disputes_list() {} + +/// Disputes - List Disputes for The Given Business Profiles +/// Lists all the Disputes for a merchant +#[utoipa::path( + get, + path = "/disputes/profile/list", + params( + ("limit" = Option, Query, description = "The maximum number of Dispute Objects to include in the response"), + ("dispute_status" = Option, Query, description = "The status of dispute"), + ("dispute_stage" = Option, Query, description = "The stage of dispute"), + ("reason" = Option, Query, description = "The reason for dispute"), + ("connector" = Option, Query, description = "The connector linked to dispute"), + ("received_time" = Option, Query, description = "The time at which dispute is received"), + ("received_time.lt" = Option, Query, description = "Time less than the dispute received time"), + ("received_time.gt" = Option, Query, description = "Time greater than the dispute received time"), + ("received_time.lte" = Option, Query, description = "Time less than or equals to the dispute received time"), + ("received_time.gte" = Option, Query, description = "Time greater than or equals to the dispute received time"), + ), + responses( + (status = 200, description = "The dispute list was retrieved successfully", body = Vec), + (status = 401, description = "Unauthorized request") + ), + tag = "Disputes", + operation_id = "List Disputes for The given Business Profiles", + security(("api_key" = [])) +)] +pub async fn retrieve_disputes_list_profile() {} diff --git a/crates/openapi/src/routes/payments.rs b/crates/openapi/src/routes/payments.rs index 653fa16c75..0e3bb9fe07 100644 --- a/crates/openapi/src/routes/payments.rs +++ b/crates/openapi/src/routes/payments.rs @@ -459,6 +459,33 @@ pub fn payments_cancel() {} )] pub fn payments_list() {} +/// Business Profile level Payments - List +/// +/// To list the payments +#[utoipa::path( + get, + path = "/payments/list", + params( + ("customer_id" = String, Query, description = "The identifier for the customer"), + ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"), + ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"), + ("limit" = i64, Query, description = "Limit on the number of objects to return"), + ("created" = PrimitiveDateTime, Query, description = "The time at which payment is created"), + ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the payment created time"), + ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the payment created time"), + ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the payment created time"), + ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the payment created time") + ), + responses( + (status = 200, description = "Received payment list"), + (status = 404, description = "No payments found") + ), + tag = "Payments", + operation_id = "List all Payments for the Profile", + security(("api_key" = [])) +)] +pub async fn profile_payments_list() {} + /// Payments - Incremental Authorization /// /// Authorized amount for a payment can be incremented if it is in status: requires_capture diff --git a/crates/openapi/src/routes/payouts.rs b/crates/openapi/src/routes/payouts.rs index 0a429041af..3f085592ef 100644 --- a/crates/openapi/src/routes/payouts.rs +++ b/crates/openapi/src/routes/payouts.rs @@ -107,6 +107,28 @@ pub async fn payouts_fulfill() {} )] pub async fn payouts_list() {} +/// Payouts - List for the Given Profiles +#[utoipa::path( + get, + path = "/payouts/profile/list", + params( + ("customer_id" = String, Query, description = "The identifier for customer"), + ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"), + ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"), + ("limit" = String, Query, description = "limit on the number of objects to return"), + ("created" = String, Query, description = "The time at which payout is created"), + ("time_range" = String, Query, description = "The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc).") + ), + responses( + (status = 200, description = "Payouts listed", body = PayoutListResponse), + (status = 404, description = "Payout not found") + ), + tag = "Payouts", + operation_id = "List payouts using generic constraints for the given Profiles", + security(("api_key" = [])) +)] +pub async fn payouts_list_profile() {} + /// Payouts - List available filters #[utoipa::path( post, @@ -136,6 +158,21 @@ pub async fn payouts_list_filters() {} )] pub async fn payouts_list_by_filter() {} +/// Payouts - List using filters for the given Profiles +#[utoipa::path( + post, + path = "/payouts/list", + request_body=PayoutListFilterConstraints, + responses( + (status = 200, description = "Payouts filtered", body = PayoutListResponse), + (status = 404, description = "Payout not found") + ), + tag = "Payouts", + operation_id = "Filter payouts using specific constraints for the given Profiles", + security(("api_key" = [])) +)] +pub async fn payouts_list_by_filter_profile() {} + /// Payouts - Confirm #[utoipa::path( post, diff --git a/crates/openapi/src/routes/refunds.rs b/crates/openapi/src/routes/refunds.rs index aa4728869b..5c72fe8b48 100644 --- a/crates/openapi/src/routes/refunds.rs +++ b/crates/openapi/src/routes/refunds.rs @@ -128,6 +128,22 @@ pub async fn refunds_update() {} )] pub fn refunds_list() {} +/// Refunds - List For the Given profiles +/// +/// Lists all the refunds associated with the merchant or a payment_id if payment_id is not provided +#[utoipa::path( + post, + path = "/refunds/profile/list", + request_body=RefundListRequest, + responses( + (status = 200, description = "List of refunds", body = RefundListResponse), + ), + tag = "Refunds", + operation_id = "List all Refunds for the given Profiles", + security(("api_key" = [])) +)] +pub fn refunds_list_profile() {} + /// Refunds - Filter /// /// To list the refunds filters associated with list of connectors, currencies and payment statuses diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index 46b679f050..80ee049484 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -544,6 +544,57 @@ pub async fn payment_connector_list( ) .await } +/// Merchant Connector - List +/// +/// List Merchant Connector Details for the merchant +#[utoipa::path( + get, + path = "/accounts/{account_id}/profile/connectors", + params( + ("account_id" = String, Path, description = "The unique identifier for the merchant account"), + ), + responses( + (status = 200, description = "Merchant Connector list retrieved successfully", body = Vec), + (status = 404, description = "Merchant Connector does not exist in records"), + (status = 401, description = "Unauthorized request") + ), + tag = "Merchant Connector Account", + operation_id = "List all Merchant Connectors for The given Profile", + security(("admin_api_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::MerchantConnectorsList))] +pub async fn payment_connector_list_profile( + state: web::Data, + req: HttpRequest, + path: web::Path, +) -> HttpResponse { + let flow = Flow::MerchantConnectorsList; + let merchant_id = path.into_inner(); + + api::server_wrap( + flow, + state, + &req, + merchant_id.to_owned(), + |state, auth, merchant_id, _| { + list_payment_connectors( + state, + merchant_id, + auth.profile_id.map(|profile_id| vec![profile_id]), + ) + }, + auth::auth_type( + &auth::AdminApiAuthWithMerchantId::default(), + &auth::JWTAuthMerchantFromRoute { + merchant_id, + required_permission: Permission::MerchantConnectorAccountRead, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + ) + .await +} /// Merchant Connector - Update /// /// To update an existing Merchant Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc. diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index ae691885b4..d52c1cef45 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -537,9 +537,18 @@ impl Payments { .route(web::get().to(payments_list)) .route(web::post().to(payments_list_by_filter)), ) + .service( + web::resource("/profile/list") + .route(web::get().to(profile_payments_list)) + .route(web::post().to(profile_payments_list_by_filter)), + ) .service(web::resource("/filter").route(web::post().to(get_filters_for_payments))) .service(web::resource("/v2/filter").route(web::get().to(get_payment_filters))) .service(web::resource("/aggregate").route(web::get().to(get_payments_aggregates))) + .service( + web::resource("/v2/profile/filter") + .route(web::get().to(get_payment_filters_profile)), + ) .service( web::resource("/{payment_id}/manual-update") .route(web::put().to(payments_manual_update)), @@ -948,8 +957,13 @@ impl Refunds { { route = route .service(web::resource("/list").route(web::post().to(refunds_list))) + .service(web::resource("/profile/list").route(web::post().to(refunds_list_profile))) .service(web::resource("/filter").route(web::post().to(refunds_filter_list))) .service(web::resource("/v2/filter").route(web::get().to(get_refunds_filters))) + .service( + web::resource("/v2/profile/filter") + .route(web::get().to(get_refunds_filters_profile)), + ) .service( web::resource("/{id}/manual-update") .route(web::put().to(refunds_manual_update)), @@ -987,6 +1001,11 @@ impl Payouts { .route(web::get().to(payouts_list)) .route(web::post().to(payouts_list_by_filter)), ) + .service( + web::resource("/profile/list") + .route(web::get().to(payouts_list_profile)) + .route(web::post().to(payouts_list_by_filter_profile)), + ) .service( web::resource("/filter").route(web::post().to(payouts_list_available_filters)), ); @@ -1218,6 +1237,10 @@ impl MerchantConnectorAccount { .route(web::post().to(connector_create)) .route(web::get().to(payment_connector_list)), ) + .service( + web::resource("/{merchant_id}/profile/connectors") + .route(web::get().to(payment_connector_list_profile)), + ) .service( web::resource("/{merchant_id}/connectors/{merchant_connector_id}") .route(web::get().to(connector_retrieve)) @@ -1369,6 +1392,9 @@ impl Disputes { web::scope("/disputes") .app_data(web::Data::new(state)) .service(web::resource("/list").route(web::get().to(retrieve_disputes_list))) + .service( + web::resource("/profile/list").route(web::get().to(retrieve_disputes_list_profile)), + ) .service(web::resource("/accept/{dispute_id}").route(web::post().to(accept_dispute))) .service( web::resource("/evidence") diff --git a/crates/router/src/routes/disputes.rs b/crates/router/src/routes/disputes.rs index a6670414f6..e8edcd704d 100644 --- a/crates/router/src/routes/disputes.rs +++ b/crates/router/src/routes/disputes.rs @@ -104,6 +104,62 @@ pub async fn retrieve_disputes_list( )) .await } + +/// Disputes - List Disputes for The Given Business Profiles +#[utoipa::path( + get, + path = "/disputes/profile/list", + params( + ("limit" = Option, Query, description = "The maximum number of Dispute Objects to include in the response"), + ("dispute_status" = Option, Query, description = "The status of dispute"), + ("dispute_stage" = Option, Query, description = "The stage of dispute"), + ("reason" = Option, Query, description = "The reason for dispute"), + ("connector" = Option, Query, description = "The connector linked to dispute"), + ("received_time" = Option, Query, description = "The time at which dispute is received"), + ("received_time.lt" = Option, Query, description = "Time less than the dispute received time"), + ("received_time.gt" = Option, Query, description = "Time greater than the dispute received time"), + ("received_time.lte" = Option, Query, description = "Time less than or equals to the dispute received time"), + ("received_time.gte" = Option, Query, description = "Time greater than or equals to the dispute received time"), + ), + responses( + (status = 200, description = "The dispute list was retrieved successfully", body = Vec), + (status = 401, description = "Unauthorized request") + ), + tag = "Disputes", + operation_id = "List Disputes for The given Business Profiles", + security(("api_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::DisputesList))] +pub async fn retrieve_disputes_list_profile( + state: web::Data, + req: HttpRequest, + payload: web::Query, +) -> HttpResponse { + let flow = Flow::DisputesList; + let payload = payload.into_inner(); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth, req, _| { + disputes::retrieve_disputes_list( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + req, + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::DisputeRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + /// Disputes - Accept Dispute #[utoipa::path( get, diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index d0c4cf42b7..11cdf4eb7e 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -1003,6 +1003,63 @@ pub async fn payments_list( )) .await } +/// Business Profile level Payments - List +/// +/// To list the payments +#[utoipa::path( + get, + path = "/payments/list", + params( + ("customer_id" = String, Query, description = "The identifier for the customer"), + ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"), + ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"), + ("limit" = i64, Query, description = "Limit on the number of objects to return"), + ("created" = PrimitiveDateTime, Query, description = "The time at which payment is created"), + ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the payment created time"), + ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the payment created time"), + ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the payment created time"), + ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the payment created time") + ), + responses( + (status = 200, description = "Received payment list"), + (status = 404, description = "No payments found") + ), + tag = "Payments", + operation_id = "List all Payments for the Profile", + security(("api_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] +#[cfg(feature = "olap")] +pub async fn profile_payments_list( + state: web::Data, + req: actix_web::HttpRequest, + payload: web::Query, +) -> impl Responder { + let flow = Flow::PaymentsList; + let payload = payload.into_inner(); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth, req, _| { + payments::list_payments( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + auth.key_store, + req, + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::PaymentRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} #[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] #[cfg(feature = "olap")] pub async fn payments_list_by_filter( @@ -1031,6 +1088,36 @@ pub async fn payments_list_by_filter( )) .await } + +#[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] +#[cfg(feature = "olap")] +pub async fn profile_payments_list_by_filter( + state: web::Data, + req: actix_web::HttpRequest, + payload: web::Json, +) -> impl Responder { + let flow = Flow::PaymentsList; + let payload = payload.into_inner(); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: auth::AuthenticationData, req, _| { + payments::apply_filters_on_payments( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + auth.key_store, + req, + ) + }, + &auth::JWTAuth(Permission::PaymentRead), + api_locking::LockAction::NotApplicable, + )) + .await +} + #[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] #[cfg(feature = "olap")] pub async fn get_filters_for_payments( @@ -1075,6 +1162,31 @@ pub async fn get_payment_filters( .await } +#[instrument(skip_all, fields(flow = ?Flow::PaymentsFilters))] +#[cfg(feature = "olap")] +pub async fn get_payment_filters_profile( + state: web::Data, + req: actix_web::HttpRequest, +) -> impl Responder { + let flow = Flow::PaymentsFilters; + Box::pin(api::server_wrap( + flow, + state, + &req, + (), + |state, auth: auth::AuthenticationData, _, _| { + payments::get_payment_filters( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + ) + }, + &auth::JWTAuth(Permission::PaymentRead), + api_locking::LockAction::NotApplicable, + )) + .await +} + #[instrument(skip_all, fields(flow = ?Flow::PaymentsAggregate))] #[cfg(feature = "olap")] pub async fn get_payments_aggregates( diff --git a/crates/router/src/routes/payouts.rs b/crates/router/src/routes/payouts.rs index 40c2e36cc5..bc14a61974 100644 --- a/crates/router/src/routes/payouts.rs +++ b/crates/router/src/routes/payouts.rs @@ -221,6 +221,41 @@ pub async fn payouts_list( .await } +/// Payouts - List Profile +#[cfg(feature = "olap")] +#[instrument(skip_all, fields(flow = ?Flow::PayoutsList))] +pub async fn payouts_list_profile( + state: web::Data, + req: HttpRequest, + json_payload: web::Query, +) -> HttpResponse { + let flow = Flow::PayoutsList; + let payload = json_payload.into_inner(); + + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth, req, _| { + payouts_list_core( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + auth.key_store, + req, + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::PayoutRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + /// Payouts - Filtered list #[cfg(feature = "olap")] #[instrument(skip_all, fields(flow = ?Flow::PayoutsList))] @@ -250,6 +285,41 @@ pub async fn payouts_list_by_filter( .await } +/// Payouts - Filtered list +#[cfg(feature = "olap")] +#[instrument(skip_all, fields(flow = ?Flow::PayoutsList))] +pub async fn payouts_list_by_filter_profile( + state: web::Data, + req: HttpRequest, + json_payload: web::Json, +) -> HttpResponse { + let flow = Flow::PayoutsList; + let payload = json_payload.into_inner(); + + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth, req, _| { + payouts_filtered_list_core( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + auth.key_store, + req, + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::PayoutRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + /// Payouts - Available filters #[cfg(feature = "olap")] #[instrument(skip_all, fields(flow = ?Flow::PayoutsFilter))] diff --git a/crates/router/src/routes/refunds.rs b/crates/router/src/routes/refunds.rs index 2a0d619e38..bdef96794f 100644 --- a/crates/router/src/routes/refunds.rs +++ b/crates/router/src/routes/refunds.rs @@ -241,6 +241,51 @@ pub async fn refunds_list( .await } +/// Refunds - List at profile level +/// +/// To list the refunds associated with a payment_id or with the merchant, if payment_id is not provided +#[utoipa::path( + post, + path = "/refunds/profile/list", + request_body=RefundListRequest, + responses( + (status = 200, description = "List of refunds", body = RefundListResponse), + ), + tag = "Refunds", + operation_id = "List all Refunds", + security(("api_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::RefundsList))] +#[cfg(feature = "olap")] +pub async fn refunds_list_profile( + state: web::Data, + req: HttpRequest, + payload: web::Json, +) -> HttpResponse { + let flow = Flow::RefundsList; + Box::pin(api::server_wrap( + flow, + state, + &req, + payload.into_inner(), + |state, auth, req, _| { + refund_list( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + req, + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::RefundRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + /// Refunds - Filter /// /// To list the refunds filters associated with list of connectors, currencies and payment statuses @@ -312,6 +357,48 @@ pub async fn get_refunds_filters(state: web::Data, req: HttpRequest) - .await } +/// Refunds - Filter V2 at profile level +/// +/// To list the refunds filters associated with list of connectors, currencies and payment statuses +#[utoipa::path( + get, + path = "/refunds/v2/filter/profile", + responses( + (status = 200, description = "List of static filters", body = RefundListFilters), + ), + tag = "Refunds", + operation_id = "List all filters for Refunds", + security(("api_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::RefundsFilters))] +#[cfg(feature = "olap")] +pub async fn get_refunds_filters_profile( + state: web::Data, + req: HttpRequest, +) -> HttpResponse { + let flow = Flow::RefundsFilters; + Box::pin(api::server_wrap( + flow, + state, + &req, + (), + |state, auth, _, _| { + get_filters_for_refunds( + state, + auth.merchant_account, + auth.profile_id.map(|profile_id| vec![profile_id]), + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth(Permission::RefundRead), + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + #[instrument(skip_all, fields(flow = ?Flow::RefundsManualUpdate))] #[cfg(feature = "olap")] pub async fn refunds_manual_update(