Bug: [FEATURE] Generate Random Disputes for sample data



### Feature Description

The issue is sub part of issue: #5991 (Please refer to this First)
The current implementation of the generate_sample_data_for_user function generates sample data for payments and refunds. However, there is no functionality to generate sample disputes. This issue is about extending the generate_sample_data_for_user function to generate random disputes based on the sample payments created.

Current Behavior
- The /sample_data API generates sample payments and refunds.
- No disputes are generated as part of the sample data generation process.

Expected Behavior
- The generate_sample_data_for_user function should also generate random disputes along with payments and refunds.
- The number of disputes generated should be based on the number of payments created:
     2 disputes if the number of payments is between 50 and 100.
     1 dispute if the number of payments is less than 50.

### Possible Implementation

Modify generate_sample_data_for_user Function:
Update the function in `utils::user::sample_data::generate_sample_data` to create sample disputes based on the number of generated payments.
The Data should be random and fields should be related to sample payments/refunds for which we are creating dispute.
Call the Db function inside `generate_sample_data_for_user` to Batch insert sample disputes
Call the Db function inside `delete_sample_data_for_user` to Delete sample disputes

Test
To generate Sample Data:
```
curl --location 'http://localhost:8080/user/sample_data' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer JWT' \
--data '{
}'
```

To Delete Sample Data:
```
curl --location --request DELETE 'http://localhost:8080/user/sample_data' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer JWT' \
--data '{

}'

```

### Have you spent some time checking if this feature request has been raised before?

- [X] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

None
diff --git a/crates/router/src/core/user/sample_data.rs b/crates/router/src/core/user/sample_data.rs
index 453b3edf00f..d098d1f76d9 100644
--- a/crates/router/src/core/user/sample_data.rs
+++ b/crates/router/src/core/user/sample_data.rs
@@ -1,6 +1,6 @@
 use api_models::user::sample_data::SampleDataRequest;
 use common_utils::errors::ReportSwitchExt;
-use diesel_models::RefundNew;
+use diesel_models::{DisputeNew, RefundNew};
 use error_stack::ResultExt;
 use hyperswitch_domain_models::payments::PaymentIntent;
 
@@ -39,19 +39,23 @@ pub async fn generate_sample_data_for_user(
         .change_context(SampleDataError::InternalServerError)
         .attach_printable("Not able to fetch merchant key store")?; // If not able to fetch merchant key store for any reason, this should be an internal server error
 
-    let (payment_intents, payment_attempts, refunds): (
+    let (payment_intents, payment_attempts, refunds, disputes): (
         Vec<PaymentIntent>,
         Vec<diesel_models::user::sample_data::PaymentAttemptBatchNew>,
         Vec<RefundNew>,
+        Vec<DisputeNew>,
     ) = sample_data.into_iter().fold(
-        (Vec::new(), Vec::new(), Vec::new()),
-        |(mut pi, mut pa, mut rf), (payment_intent, payment_attempt, refund)| {
+        (Vec::new(), Vec::new(), Vec::new(), Vec::new()),
+        |(mut pi, mut pa, mut rf, mut dp), (payment_intent, payment_attempt, refund, dispute)| {
             pi.push(payment_intent);
             pa.push(payment_attempt);
             if let Some(refund) = refund {
                 rf.push(refund);
             }
-            (pi, pa, rf)
+            if let Some(dispute) = dispute {
+                dp.push(dispute);
+            }
+            (pi, pa, rf, dp)
         },
     );
 
@@ -70,6 +74,11 @@ pub async fn generate_sample_data_for_user(
         .insert_refunds_batch_for_sample_data(refunds)
         .await
         .switch()?;
+    state
+        .store
+        .insert_disputes_batch_for_sample_data(disputes)
+        .await
+        .switch()?;
 
     Ok(ApplicationResponse::StatusOk)
 }
@@ -109,6 +118,11 @@ pub async fn delete_sample_data_for_user(
         .delete_refunds_for_sample_data(&merchant_id_del)
         .await
         .switch()?;
+    state
+        .store
+        .delete_disputes_for_sample_data(&merchant_id_del)
+        .await
+        .switch()?;
 
     Ok(ApplicationResponse::StatusOk)
 }
diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs
index ea2556a5151..4f859d8e56a 100644
--- a/crates/router/src/utils/user/sample_data.rs
+++ b/crates/router/src/utils/user/sample_data.rs
@@ -8,7 +8,7 @@ use common_utils::{
 };
 #[cfg(feature = "v1")]
 use diesel_models::user::sample_data::PaymentAttemptBatchNew;
-use diesel_models::RefundNew;
+use diesel_models::{enums as storage_enums, DisputeNew, RefundNew};
 use error_stack::ResultExt;
 use hyperswitch_domain_models::payments::PaymentIntent;
 use rand::{prelude::SliceRandom, thread_rng, Rng};
@@ -27,7 +27,14 @@ pub async fn generate_sample_data(
     req: SampleDataRequest,
     merchant_id: &id_type::MerchantId,
     org_id: &id_type::OrganizationId,
-) -> SampleDataResult<Vec<(PaymentIntent, PaymentAttemptBatchNew, Option<RefundNew>)>> {
+) -> SampleDataResult<
+    Vec<(
+        PaymentIntent,
+        PaymentAttemptBatchNew,
+        Option<RefundNew>,
+        Option<DisputeNew>,
+    )>,
+> {
     let sample_data_size: usize = req.record.unwrap_or(100);
     let key_manager_state = &state.into();
     if !(10..=100).contains(&sample_data_size) {
@@ -120,13 +127,23 @@ pub async fn generate_sample_data(
 
     let mut refunds_count = 0;
 
+    // 2 disputes if generated data size is between 50 and 100, 1 dispute if it is less than 50.
+    let number_of_disputes: usize = if sample_data_size >= 50 { 2 } else { 1 };
+
+    let mut disputes_count = 0;
+
     let mut random_array: Vec<usize> = (1..=sample_data_size).collect();
 
     // Shuffle the array
     let mut rng = thread_rng();
     random_array.shuffle(&mut rng);
 
-    let mut res: Vec<(PaymentIntent, PaymentAttemptBatchNew, Option<RefundNew>)> = Vec::new();
+    let mut res: Vec<(
+        PaymentIntent,
+        PaymentAttemptBatchNew,
+        Option<RefundNew>,
+        Option<DisputeNew>,
+    )> = Vec::new();
     let start_time = req
         .start_time
         .unwrap_or(common_utils::date_time::now() - time::Duration::days(7))
@@ -353,7 +370,7 @@ pub async fn generate_sample_data(
                 internal_reference_id: common_utils::generate_id_with_default_len("test"),
                 external_reference_id: None,
                 payment_id: payment_id.clone(),
-                attempt_id,
+                attempt_id: attempt_id.clone(),
                 merchant_id: merchant_id.clone(),
                 connector_transaction_id,
                 connector_refund_id: None,
@@ -387,7 +404,43 @@ pub async fn generate_sample_data(
             None
         };
 
-        res.push((payment_intent, payment_attempt, refund));
+        let dispute =
+            if disputes_count < number_of_disputes && !is_failed_payment && refund.is_none() {
+                disputes_count += 1;
+                Some(DisputeNew {
+                    dispute_id: common_utils::generate_id_with_default_len("test"),
+                    amount: (amount * 100).to_string(),
+                    currency: payment_intent
+                        .currency
+                        .unwrap_or(common_enums::Currency::USD)
+                        .to_string(),
+                    dispute_stage: storage_enums::DisputeStage::Dispute,
+                    dispute_status: storage_enums::DisputeStatus::DisputeOpened,
+                    payment_id: payment_id.clone(),
+                    attempt_id: attempt_id.clone(),
+                    merchant_id: merchant_id.clone(),
+                    connector_status: "Sample connector status".into(),
+                    connector_dispute_id: common_utils::generate_id_with_default_len("test"),
+                    connector_reason: Some("Sample Dispute".into()),
+                    connector_reason_code: Some("123".into()),
+                    challenge_required_by: None,
+                    connector_created_at: None,
+                    connector_updated_at: None,
+                    connector: payment_attempt
+                        .connector
+                        .clone()
+                        .unwrap_or(DummyConnector4.to_string()),
+                    evidence: None,
+                    profile_id: payment_intent.profile_id.clone(),
+                    merchant_connector_id: payment_attempt.merchant_connector_id.clone(),
+                    dispute_amount: amount * 100,
+                    organization_id: org_id.clone(),
+                })
+            } else {
+                None
+            };
+
+        res.push((payment_intent, payment_attempt, refund, dispute));
     }
     Ok(res)
 }

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
I added dispute generation to function `generate_sample_data` in `utils/user/sample_data.rs`. 
The number of disputes generated is based on the number of payments created:
2 disputes if the number of payments is between 50 and 100.
1 dispute if the number of payments is less than 50.

Other changes I made is just to accommodate the dispute generation code changes.

### Additional Changes

- [x] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
#6117 


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
Tested manually.

Initial state for both Case1 and Case2:
Before sending POST request to `sample_data`, there are 18 non-generated `payment_attempt` records, and 0 `dispute` record.
<img width="1384" alt="image" src="https://github.com/user-attachments/assets/a97abf7e-34d4-4bc2-b5e6-fd7ff2908c94">
<img width="1146" alt="image" src="https://github.com/user-attachments/assets/31dddc64-7063-41e3-80d0-c57d378debcf">

#### Case 1: 2 disputes if the number of payments is between 50 and 100.
We send a POST request without payload to `sample_data`, by default, 100 `payment_attempt` records will be generated, along with 2 `dispute`. Now there are 118 generated `pyament_attempt` records, and 2 `dispute` records with `test_` prefixed `dispute_id`.
<img width="1107" alt="image" src="https://github.com/user-attachments/assets/df612a03-dc3d-4af2-9588-a5b4381f7c09">
<img width="1384" alt="image" src="https://github.com/user-attachments/assets/16d5f449-4f92-417f-991e-8ddb4e9f2548">

#### Case 2: 1 dispute if the number of payments is less than 50.
We send a POST request with payload `{ "record": 30 }` to `sample_data`, 30 `payment_attempt` records will be generated, along with 1 `dispute`. Now there are 48 generated `pyament_attempt` records, and 1 `dispute` records with `test_` prefixed `dispute_id`.
<img width="1364" alt="image" src="https://github.com/user-attachments/assets/5e9f1712-3be2-4b88-acac-08ac866e64df">
<img width="1385" alt="image" src="https://github.com/user-attachments/assets/a2efec0a-cbec-4154-8d86-98aa5aecb3de">

#### Case Delete:
When there exists data generated by `sample_api`, sending a `DELETE` request to `sample_api` deletes all the generated sample data (back to initial state in this example).
<img width="1076" alt="image" src="https://github.com/user-attachments/assets/42414fe0-11d0-40ae-987d-7d0c8fd19d4b">
<img width="1057" alt="image" src="https://github.com/user-attachments/assets/4fe4cbba-21de-4b69-82f6-5049e61f69a6">



## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
