From 7d0662ff6e84f687540b6a92c1b674c2ee5c64d2 Mon Sep 17 00:00:00 2001 From: abdulhakim2902 Date: Sun, 5 Feb 2023 17:26:40 +0700 Subject: [PATCH] fix: handle order refunded when genetic testing rejected --- pallets/genetic-testing/src/lib.rs | 9 +++ pallets/orders/src/functions.rs | 100 ++++++++++++++++++++++++++++- pallets/orders/src/lib.rs | 1 + pallets/orders/traits/src/lib.rs | 2 +- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/pallets/genetic-testing/src/lib.rs b/pallets/genetic-testing/src/lib.rs index 303b94f3..f40fecdb 100644 --- a/pallets/genetic-testing/src/lib.rs +++ b/pallets/genetic-testing/src/lib.rs @@ -175,6 +175,7 @@ pub mod pallet { DataStakerNotFound, DataHashNotFound, UnpaidOrder, + RefundFailed, } pub type HashOf = ::Hash; @@ -412,6 +413,14 @@ impl GeneticTestingInterface for Pallet { dna_sample.status = DnaSampleStatus::Rejected; dna_sample.updated_at = now; DnaSamples::::insert(tracking_id, &dna_sample); + + let succeed = T::Orders::update_status_failed(&dna_sample.order_id); + + if !succeed { + return Err(Error::::RefundFailed) + } + + T::Orders::emit_event_order_failed(&dna_sample.order_id); T::Orders::remove_order_id_from_pending_orders_by_seller( &dna_sample.lab_id, &dna_sample.order_id, diff --git a/pallets/orders/src/functions.rs b/pallets/orders/src/functions.rs index 8bc3b794..356b3c57 100644 --- a/pallets/orders/src/functions.rs +++ b/pallets/orders/src/functions.rs @@ -2,7 +2,10 @@ use crate::*; use frame_support::{ pallet_prelude::*, - sp_runtime::{traits::Hash, SaturatedConversion}, + sp_runtime::{ + traits::{Hash, Zero}, + SaturatedConversion, + }, traits::{fungibles, Currency, ExistenceRequirement}, }; use primitives_price_and_currency::CurrencyType; @@ -135,6 +138,44 @@ impl Pallet { Ok(Some(asset_id)) } + pub fn do_balance_sufficient( + sender: &T::AccountId, + amount: &BalanceOf, + asset_id: Option, + ) -> Result<(), Error> { + if let Some(asset_id) = asset_id { + let min_asset_balance = + >::minimum_balance(asset_id); + let current_asset_balance = + >::balance(asset_id, sender); + let transferable_asset_balance = if current_asset_balance >= min_asset_balance { + current_asset_balance - min_asset_balance + } else { + 0u128 + }; + + if (*amount).saturated_into::() > transferable_asset_balance { + return Err(Error::::InsufficientBalance) + } + + return Ok(()) + } + + let minimum_balance = CurrencyOf::::minimum_balance(); + let current_balance = CurrencyOf::::free_balance(sender); + let transferable_balance = if current_balance >= minimum_balance { + current_balance - minimum_balance + } else { + Zero::zero() + }; + + if *amount > transferable_balance { + return Err(Error::::InsufficientBalance) + } + + Ok(()) + } + pub fn do_transfer( currency: &CurrencyType, sender: &T::AccountId, @@ -143,12 +184,15 @@ impl Pallet { asset_id: Option, keep_alive: bool, ) -> Result<(), Error> { + let _ = Self::do_balance_sufficient(sender, &amount, asset_id)?; + if currency == &CurrencyType::DBIO { let existence = if keep_alive { ExistenceRequirement::KeepAlive } else { ExistenceRequirement::AllowDeath }; + let result = CurrencyOf::::transfer(sender, receiver, amount, existence); if let Err(dispatch) = result { @@ -174,6 +218,8 @@ impl Pallet { keep_alive, ); + // check balance + if let Err(dispatch) = result { return match dispatch { DispatchError::Other(_) => Err(Error::::Other), @@ -203,11 +249,59 @@ impl OrderEventEmitter for Pallet { } impl OrderStatusUpdater for Pallet { - fn update_status_failed(order_id: &HashOf) { + fn update_status_failed(order_id: &HashOf) -> bool { match Self::order_by_id(order_id) { - None => Self::deposit_event(Event::OrderNotFound), + None => { + Self::deposit_event(Event::OrderNotFound); + false + }, Some(order) => { + if !order.currency.can_transfer() { + return false + } + + let pallet_id = Self::pallet_id(); + + if pallet_id.is_none() { + return false + } + + let pallet_id = pallet_id.unwrap(); + + let mut testing_price = Zero::zero(); + let mut qc_price = Zero::zero(); + + for price in order.prices.iter() { + testing_price += price.value; + } + + for price in order.additional_prices.iter() { + qc_price += price.value; + } + + // TODO: check balance; + + let _ = Self::do_transfer( + &order.currency, + &pallet_id, + order.get_seller_id(), + qc_price, + order.asset_id, + false, + ); + + let _ = Self::do_transfer( + &order.currency, + &pallet_id, + &order.customer_id, + testing_price, + order.asset_id, + false, + ); + Self::update_order_status(&order.id, OrderStatus::Failed); + + true }, } } diff --git a/pallets/orders/src/lib.rs b/pallets/orders/src/lib.rs index 9bc0aad3..c90f7b80 100644 --- a/pallets/orders/src/lib.rs +++ b/pallets/orders/src/lib.rs @@ -209,6 +209,7 @@ pub mod pallet { NoProviders, Token, Arithmetic, + InsufficientBalance, } #[pallet::call] diff --git a/pallets/orders/traits/src/lib.rs b/pallets/orders/traits/src/lib.rs index ef82e920..01c89105 100644 --- a/pallets/orders/traits/src/lib.rs +++ b/pallets/orders/traits/src/lib.rs @@ -7,7 +7,7 @@ pub trait OrderEventEmitter { } pub trait OrderStatusUpdater { - fn update_status_failed(order_id: &T::Hash); + fn update_status_failed(order_id: &T::Hash) -> bool; fn remove_order_id_from_pending_orders_by_seller( seller_id: &T::AccountId, genetic_analysis_order_id: &T::Hash,