mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	feat(router): add delete_evidence api for disputes (#3608)
				
					
				
			This commit is contained in:
		 Sai Harsha Vardhan
					Sai Harsha Vardhan
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							b6754a7de8
						
					
				
				
					commit
					1dc660f804
				
			| @ -79,7 +79,7 @@ pub struct DisputeResponsePaymentsRetrieve { | ||||
|     pub created_at: PrimitiveDateTime, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Serialize, strum::Display, Clone)] | ||||
| #[derive(Debug, Serialize, Deserialize, strum::Display, Clone)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| #[strum(serialize_all = "snake_case")] | ||||
| pub enum EvidenceType { | ||||
| @ -196,3 +196,11 @@ pub struct SubmitEvidenceRequest { | ||||
|     /// Any additional evidence statements | ||||
|     pub uncategorized_text: Option<String>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] | ||||
| pub struct DeleteEvidenceRequest { | ||||
|     /// Id of the dispute | ||||
|     pub dispute_id: String, | ||||
|     /// Evidence Type to be deleted | ||||
|     pub evidence_type: EvidenceType, | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| use common_utils::events::{ApiEventMetric, ApiEventsType}; | ||||
|  | ||||
| use super::{DisputeResponse, DisputeResponsePaymentsRetrieve, SubmitEvidenceRequest}; | ||||
| use super::{ | ||||
|     DeleteEvidenceRequest, DisputeResponse, DisputeResponsePaymentsRetrieve, SubmitEvidenceRequest, | ||||
| }; | ||||
|  | ||||
| impl ApiEventMetric for SubmitEvidenceRequest { | ||||
|     fn get_api_event_type(&self) -> Option<ApiEventsType> { | ||||
| @ -23,3 +25,10 @@ impl ApiEventMetric for DisputeResponse { | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| impl ApiEventMetric for DeleteEvidenceRequest { | ||||
|     fn get_api_event_type(&self) -> Option<ApiEventsType> { | ||||
|         Some(ApiEventsType::Dispute { | ||||
|             dispute_id: self.dispute_id.clone(), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -423,3 +423,43 @@ pub async fn retrieve_dispute_evidence( | ||||
|         transformers::get_dispute_evidence_vec(&state, merchant_account, dispute_evidence).await?; | ||||
|     Ok(services::ApplicationResponse::Json(dispute_evidence_vec)) | ||||
| } | ||||
|  | ||||
| pub async fn delete_evidence( | ||||
|     state: AppState, | ||||
|     merchant_account: domain::MerchantAccount, | ||||
|     delete_evidence_request: dispute_models::DeleteEvidenceRequest, | ||||
| ) -> RouterResponse<serde_json::Value> { | ||||
|     let dispute_id = delete_evidence_request.dispute_id.clone(); | ||||
|     let dispute = state | ||||
|         .store | ||||
|         .find_dispute_by_merchant_id_dispute_id(&merchant_account.merchant_id, &dispute_id) | ||||
|         .await | ||||
|         .to_not_found_response(errors::ApiErrorResponse::DisputeNotFound { | ||||
|             dispute_id: dispute_id.clone(), | ||||
|         })?; | ||||
|     let dispute_evidence: api::DisputeEvidence = dispute | ||||
|         .evidence | ||||
|         .clone() | ||||
|         .parse_value("DisputeEvidence") | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|         .attach_printable("Error while parsing dispute evidence record")?; | ||||
|     let updated_dispute_evidence = | ||||
|         transformers::delete_evidence_file(dispute_evidence, delete_evidence_request.evidence_type); | ||||
|     let update_dispute = diesel_models::dispute::DisputeUpdate::EvidenceUpdate { | ||||
|         evidence: utils::Encode::<api::DisputeEvidence>::encode_to_value(&updated_dispute_evidence) | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|             .attach_printable("Error while encoding dispute evidence")? | ||||
|             .into(), | ||||
|     }; | ||||
|     state | ||||
|         .store | ||||
|         .update_dispute(dispute, update_dispute) | ||||
|         .await | ||||
|         .to_not_found_response(errors::ApiErrorResponse::DisputeNotFound { | ||||
|             dispute_id: dispute_id.to_owned(), | ||||
|         }) | ||||
|         .attach_printable_lazy(|| { | ||||
|             format!("Unable to update dispute with dispute_id: {dispute_id}") | ||||
|         })?; | ||||
|     Ok(services::ApplicationResponse::StatusOk) | ||||
| } | ||||
|  | ||||
| @ -222,6 +222,54 @@ pub async fn get_dispute_evidence_block( | ||||
|     }) | ||||
| } | ||||
|  | ||||
| pub fn delete_evidence_file( | ||||
|     dispute_evidence: DisputeEvidence, | ||||
|     evidence_type: EvidenceType, | ||||
| ) -> DisputeEvidence { | ||||
|     match evidence_type { | ||||
|         EvidenceType::CancellationPolicy => DisputeEvidence { | ||||
|             cancellation_policy: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::CustomerCommunication => DisputeEvidence { | ||||
|             customer_communication: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::CustomerSignature => DisputeEvidence { | ||||
|             customer_signature: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::Receipt => DisputeEvidence { | ||||
|             receipt: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::RefundPolicy => DisputeEvidence { | ||||
|             refund_policy: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::ServiceDocumentation => DisputeEvidence { | ||||
|             service_documentation: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::ShippingDocumentation => DisputeEvidence { | ||||
|             shipping_documentation: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::InvoiceShowingDistinctTransactions => DisputeEvidence { | ||||
|             invoice_showing_distinct_transactions: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::RecurringTransactionAgreement => DisputeEvidence { | ||||
|             recurring_transaction_agreement: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|         EvidenceType::UncategorizedFile => DisputeEvidence { | ||||
|             uncategorized_file: None, | ||||
|             ..dispute_evidence | ||||
|         }, | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn get_dispute_evidence_vec( | ||||
|     state: &AppState, | ||||
|     merchant_account: domain::MerchantAccount, | ||||
|  | ||||
| @ -848,7 +848,8 @@ impl Disputes { | ||||
|             .service( | ||||
|                 web::resource("/evidence") | ||||
|                     .route(web::post().to(submit_dispute_evidence)) | ||||
|                     .route(web::put().to(attach_dispute_evidence)), | ||||
|                     .route(web::put().to(attach_dispute_evidence)) | ||||
|                     .route(web::delete().to(delete_dispute_evidence)), | ||||
|             ) | ||||
|             .service( | ||||
|                 web::resource("/evidence/{dispute_id}") | ||||
|  | ||||
| @ -264,3 +264,41 @@ pub async fn retrieve_dispute_evidence( | ||||
|     )) | ||||
|     .await | ||||
| } | ||||
|  | ||||
| /// Disputes - Delete Evidence attached to a Dispute | ||||
| /// | ||||
| /// To delete an evidence file attached to a dispute | ||||
| #[utoipa::path( | ||||
|     put, | ||||
|     path = "/disputes/evidence", | ||||
|     request_body=DeleteEvidenceRequest, | ||||
|     responses( | ||||
|         (status = 200, description = "Evidence deleted from a dispute"), | ||||
|         (status = 400, description = "Bad Request") | ||||
|     ), | ||||
|     tag = "Disputes", | ||||
|     operation_id = "Delete Evidence attached to a Dispute", | ||||
|     security(("api_key" = [])) | ||||
| )] | ||||
| #[instrument(skip_all, fields(flow = ?Flow::DeleteDisputeEvidence))] | ||||
| pub async fn delete_dispute_evidence( | ||||
|     state: web::Data<AppState>, | ||||
|     req: HttpRequest, | ||||
|     json_payload: web::Json<dispute_models::DeleteEvidenceRequest>, | ||||
| ) -> HttpResponse { | ||||
|     let flow = Flow::DeleteDisputeEvidence; | ||||
|     Box::pin(api::server_wrap( | ||||
|         flow, | ||||
|         state, | ||||
|         &req, | ||||
|         json_payload.into_inner(), | ||||
|         |state, auth, req| disputes::delete_evidence(state, auth.merchant_account, req), | ||||
|         auth::auth_type( | ||||
|             &auth::ApiKeyAuth, | ||||
|             &auth::JWTAuth(Permission::DisputeWrite), | ||||
|             req.headers(), | ||||
|         ), | ||||
|         api_locking::LockAction::NotApplicable, | ||||
|     )) | ||||
|     .await | ||||
| } | ||||
|  | ||||
| @ -136,7 +136,8 @@ impl From<Flow> for ApiIdentifier { | ||||
|             | Flow::DisputesList | ||||
|             | Flow::DisputesEvidenceSubmit | ||||
|             | Flow::AttachDisputeEvidence | ||||
|             | Flow::RetrieveDisputeEvidence => Self::Disputes, | ||||
|             | Flow::RetrieveDisputeEvidence | ||||
|             | Flow::DeleteDisputeEvidence => Self::Disputes, | ||||
|  | ||||
|             Flow::CardsInfo => Self::CardsInfo, | ||||
|  | ||||
|  | ||||
| @ -235,6 +235,8 @@ pub enum Flow { | ||||
|     CreateConfigKey, | ||||
|     /// Attach Dispute Evidence flow | ||||
|     AttachDisputeEvidence, | ||||
|     /// Delete Dispute Evidence flow | ||||
|     DeleteDisputeEvidence, | ||||
|     /// Retrieve Dispute Evidence flow | ||||
|     RetrieveDisputeEvidence, | ||||
|     /// Invalidate cache flow | ||||
|  | ||||
		Reference in New Issue
	
	Block a user