Bug: [FEATURE]: add `offset` field to mandates list



### Feature Description

The [mandates list](https://github.com/juspay/hyperswitch/blob/54c0b218d9f20c6388dde0f30ea525011cdad573/crates/router/src/routes/mandates.rs#L114) endpoint currently has no field to specify `offset`, which would skip certain number of entries from the start. This is necessary in order to provide pagination support.

### Possible Implementation

accept a field called `offset` which specifies the number of items to skip from the start.

This would be similar to the `payments_list` pagination. Refer [here](https://github.com/juspay/hyperswitch/blob/54c0b218d9f20c6388dde0f30ea525011cdad573/crates/router/src/routes/payments.rs#L868)

### 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/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs
index 7c20a902d28..bd5c5b5a1a0 100644
--- a/crates/api_models/src/mandates.rs
+++ b/crates/api_models/src/mandates.rs
@@ -87,6 +87,8 @@ pub struct MandateCardDetails {
 pub struct MandateListConstraints {
     /// limit on the number of objects to return
     pub limit: Option<i64>,
+    /// offset on the number of objects to return
+    pub offset: Option<i64>,
     /// status of the mandate
     pub mandate_status: Option<api_enums::MandateStatus>,
     /// connector linked to mandate
diff --git a/crates/router/src/db/mandate.rs b/crates/router/src/db/mandate.rs
index eb2859e57e1..936344f5af5 100644
--- a/crates/router/src/db/mandate.rs
+++ b/crates/router/src/db/mandate.rs
@@ -262,14 +262,22 @@ impl MandateInterface for MockDb {
             checker
         });
 
+        #[allow(clippy::as_conversions)]
+        let offset = (if mandate_constraints.offset.unwrap_or(0) < 0 {
+            0
+        } else {
+            mandate_constraints.offset.unwrap_or(0)
+        }) as usize;
+
         let mandates: Vec<storage::Mandate> = if let Some(limit) = mandate_constraints.limit {
             #[allow(clippy::as_conversions)]
             mandates_iter
+                .skip(offset)
                 .take((if limit < 0 { 0 } else { limit }) as usize)
                 .cloned()
                 .collect()
         } else {
-            mandates_iter.cloned().collect()
+            mandates_iter.skip(offset).cloned().collect()
         };
         Ok(mandates)
     }
diff --git a/crates/router/src/routes/mandates.rs b/crates/router/src/routes/mandates.rs
index 1203b766cbb..3e47d78da8a 100644
--- a/crates/router/src/routes/mandates.rs
+++ b/crates/router/src/routes/mandates.rs
@@ -101,6 +101,7 @@ pub async fn revoke_mandate(
         ("created_time.gt" = Option<PrimitiveDateTime>, Query, description = "Time greater than the mandate created time"),
         ("created_time.lte" = Option<PrimitiveDateTime>, Query, description = "Time less than or equals to the mandate created time"),
         ("created_time.gte" = Option<PrimitiveDateTime>, Query, description = "Time greater than or equals to the mandate created time"),
+        ("offset" = Option<i64>, Query, description = "The number of Mandate Objects to skip when retrieving the list Mandates."),
     ),
     responses(
         (status = 200, description = "The mandate list was retrieved successfully", body = Vec<MandateResponse>),
diff --git a/crates/router/src/types/storage/mandate.rs b/crates/router/src/types/storage/mandate.rs
index 32c0798e95c..05a5733053f 100644
--- a/crates/router/src/types/storage/mandate.rs
+++ b/crates/router/src/types/storage/mandate.rs
@@ -54,6 +54,9 @@ impl MandateDbExt for Mandate {
         if let Some(limit) = mandate_list_constraints.limit {
             filter = filter.limit(limit);
         }
+        if let Some(offset) = mandate_list_constraints.offset {
+            filter = filter.offset(offset);
+        }
 
         logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg, _>(&filter).to_string());
 

## 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 -->
Add offset to mandate list endpoint.
Closes #3748 

### 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).
-->


## 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)?
-->
- Create 10 mandates.
- Use the below curl to list the first 5 mandates.
```bash
curl --location 'http://localhost:8080/mandates/list?limit=5' \
--header 'api-key: dev_dg0YfZam6V6VM2KBPFLr0olm6kGM3QojUE9Ba6f8Gzzi7IIAnkN4fyfKsyc55pB4'
```

- Use the below curl to list next 5 mandates.
```bash
curl --location 'http://localhost:8080/mandates/list?limit=5&offset=5' \
--header 'api-key: dev_dg0YfZam6V6VM2KBPFLr0olm6kGM3QojUE9Ba6f8Gzzi7IIAnkN4fyfKsyc55pB4'
```

## 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
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
