Bug: [BUG] merchant account delete does not delete the `merchant_key_store`



### Bug Description

When a merchant is created a `merchant_key_store` is created, which goes along with the `merchant_account`. But when the merchant account is deleted, the key store is not deleted. 

### Expected Behavior

Both merchant account and key store should be delted.

### Actual Behavior

The key store still exists. 

### Steps To Reproduce

- Create a merchant account.
- Delete the merchant account.

### Context For The Bug

_No response_

### Environment

Local

### Have you spent some time checking if this bug 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?

No, but I'm happy to collaborate on a PR with someone else
diff --git a/crates/diesel_models/src/query/merchant_key_store.rs b/crates/diesel_models/src/query/merchant_key_store.rs
index 02a31a1f397..27ec3be9fcd 100644
--- a/crates/diesel_models/src/query/merchant_key_store.rs
+++ b/crates/diesel_models/src/query/merchant_key_store.rs
@@ -27,4 +27,16 @@ impl MerchantKeyStore {
         )
         .await
     }
+
+    #[instrument(skip(conn))]
+    pub async fn delete_by_merchant_id(
+        conn: &PgPooledConn,
+        merchant_id: &str,
+    ) -> StorageResult<bool> {
+        generics::generic_delete::<<Self as HasTable>::Table, _>(
+            conn,
+            dsl::merchant_id.eq(merchant_id.to_owned()),
+        )
+        .await
+    }
 }
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index a6847968c28..5553e9be92d 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -465,11 +465,19 @@ pub async fn merchant_account_delete(
     state: AppState,
     merchant_id: String,
 ) -> RouterResponse<api::MerchantAccountDeleteResponse> {
+    let mut is_deleted = false;
     let db = state.store.as_ref();
-    let is_deleted = db
+    let is_merchant_account_deleted = db
         .delete_merchant_account_by_merchant_id(&merchant_id)
         .await
         .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
+    if is_merchant_account_deleted {
+        let is_merchant_key_store_deleted = db
+            .delete_merchant_key_store_by_merchant_id(&merchant_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
+        is_deleted = is_merchant_account_deleted && is_merchant_key_store_deleted;
+    }
     let response = api::MerchantAccountDeleteResponse {
         merchant_id,
         deleted: is_deleted,
diff --git a/crates/router/src/db/merchant_key_store.rs b/crates/router/src/db/merchant_key_store.rs
index 8cb93fc369b..970e2b77032 100644
--- a/crates/router/src/db/merchant_key_store.rs
+++ b/crates/router/src/db/merchant_key_store.rs
@@ -1,7 +1,7 @@
 use error_stack::{IntoReport, ResultExt};
 use masking::Secret;
 #[cfg(feature = "accounts_cache")]
-use storage_impl::redis::cache::ACCOUNTS_CACHE;
+use storage_impl::redis::cache::{CacheKind, ACCOUNTS_CACHE};
 
 use crate::{
     connection,
@@ -27,6 +27,11 @@ pub trait MerchantKeyStoreInterface {
         merchant_id: &str,
         key: &Secret<Vec<u8>>,
     ) -> CustomResult<domain::MerchantKeyStore, errors::StorageError>;
+
+    async fn delete_merchant_key_store_by_merchant_id(
+        &self,
+        merchant_id: &str,
+    ) -> CustomResult<bool, errors::StorageError>;
 }
 
 #[async_trait::async_trait]
@@ -66,6 +71,7 @@ impl MerchantKeyStoreInterface for Store {
             .map_err(Into::into)
             .into_report()
         };
+
         #[cfg(not(feature = "accounts_cache"))]
         {
             fetch_func()
@@ -90,6 +96,38 @@ impl MerchantKeyStoreInterface for Store {
             .change_context(errors::StorageError::DecryptionError)
         }
     }
+
+    async fn delete_merchant_key_store_by_merchant_id(
+        &self,
+        merchant_id: &str,
+    ) -> CustomResult<bool, errors::StorageError> {
+        let delete_func = || async {
+            let conn = connection::pg_connection_write(self).await?;
+            diesel_models::merchant_key_store::MerchantKeyStore::delete_by_merchant_id(
+                &conn,
+                merchant_id,
+            )
+            .await
+            .map_err(Into::into)
+            .into_report()
+        };
+
+        #[cfg(not(feature = "accounts_cache"))]
+        {
+            delete_func().await
+        }
+
+        #[cfg(feature = "accounts_cache")]
+        {
+            let key_store_cache_key = format!("merchant_key_store_{}", merchant_id);
+            super::cache::publish_and_redact(
+                self,
+                CacheKind::Accounts(key_store_cache_key.into()),
+                delete_func,
+            )
+            .await
+        }
+    }
 }
 
 #[async_trait::async_trait]
@@ -140,6 +178,22 @@ impl MerchantKeyStoreInterface for MockDb {
             .await
             .change_context(errors::StorageError::DecryptionError)
     }
+
+    async fn delete_merchant_key_store_by_merchant_id(
+        &self,
+        merchant_id: &str,
+    ) -> CustomResult<bool, errors::StorageError> {
+        let mut merchant_key_stores = self.merchant_key_store.lock().await;
+        let index = merchant_key_stores
+            .iter()
+            .position(|mks| mks.merchant_id == merchant_id)
+            .ok_or(errors::StorageError::ValueNotFound(format!(
+                "No merchant key store found for merchant_id = {}",
+                merchant_id
+            )))?;
+        merchant_key_stores.remove(index);
+        Ok(true)
+    }
 }
 
 #[cfg(test)]

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

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

## Description
<!-- Describe your changes in detail -->
Closes #2154 by calling `delete_merchant_key_store_by_merchant_id` at `merchant_account_delete`

### Additional Changes

- [ ] 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)?
-->


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