feat: Major transactions past 30 days

docker3
Miroito 3 years ago
parent a8c533f909
commit 6d61842df1

747
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,7 +1,9 @@
use crate::api::{
types::{
paginated_response::PaginatedResponse,
transaction::{LatestTransaction, TransactionCompany, TransactionsAggregated},
transaction::{
LatestTransaction, MajorTransactions, TransactionCompany, TransactionsAggregated,
},
},
FastInsidersApi,
};
@ -105,4 +107,32 @@ impl FastInsidersApi {
Ok(res)
}
pub async fn get_major_transactions(
&self,
_: Option<String>,
page: i64,
size: i64,
) -> Result<PaginatedResponse<MajorTransactions>, ()> {
let route = &format!("{}/transaction/major?page={}&size={}", self.url, page, size,);
#[cfg(client)]
let res = reqwasm::http::Request::get(route)
.send()
.await
.map_err(|_| ())?
.json::<PaginatedResponse<MajorTransactions>>()
.await
.map_err(|_| ())?;
#[cfg(engine)]
let res = reqwest::get(route)
.await
.map_err(|_| ())?
.json::<PaginatedResponse<MajorTransactions>>()
.await
.map_err(|_| ())?;
Ok(res)
}
}

@ -3,7 +3,7 @@ use sycamore::prelude::*;
use crate::components::base_table::TableContent;
use super::transaction::{TransactionCompany, TransactionsAggregated, LatestTransaction};
use super::transaction::{TransactionCompany, TransactionsAggregated, LatestTransaction, MajorTransactions};
pub trait IntoTableData<G>
where
@ -143,3 +143,50 @@ where
}
}
}
impl<G> IntoTableData<G> for PaginatedResponse<MajorTransactions>
where
G: GenericNode,
{
fn into_table_data(self, cx: Scope) -> TableContent<G> {
let headers_view = vec![
view! {cx, "Company" },
view! {cx, "Date published" },
view! {cx, "Date executed" },
view! {cx, "Nature" },
view! {cx, "Instrument" },
view! {cx, "Volume" },
view! {cx, "Unit price" },
view! {cx, "Total" },
];
let data_view: Vec<Vec<View<G>>> = self
.list
.into_iter()
.map(|t| {
let mut res = vec![];
res.push(view! {cx,
a (href=format!("transactions/{}", t.slug),
class="text-indigo-800 dark:text-indigo-300 hover:text-indigo-500 hover:underline dark:hover:text-indigo-600",
) {
(t.company_name.to_owned())
}
});
res.push(view! {cx, (t.date_published.to_owned()) });
res.push(view! {cx, (t.date_executed.to_owned()) });
res.push(view! {cx, (t.nature.to_owned()) });
res.push(view! {cx, (t.instrument.to_owned()) });
res.push(view! {cx, (t.volume.to_owned()) });
res.push(view! {cx, (t.unit_price.to_owned()) });
res.push(view! {cx, (t.total.to_string()) });
res
})
.collect();
TableContent {
headers_view,
data_view,
}
}
}

@ -52,3 +52,16 @@ pub struct LatestTransaction {
pub nature: String,
pub total: f32,
}
#[derive(Deserialize, Clone)]
pub struct MajorTransactions {
pub company_name: String,
pub slug: String,
pub date_published: NaiveDate,
pub date_executed: NaiveDate,
pub nature: String,
pub instrument: String,
pub volume: i32,
pub unit_price: f32,
pub total: f32,
}

@ -2,7 +2,7 @@ use perseus::prelude::*;
use sycamore::prelude::*;
use crate::{
api::types::transaction::{LatestTransaction, TransactionsAggregated},
api::types::transaction::{LatestTransaction, MajorTransactions, TransactionsAggregated},
components::{
main_content_container::MainContentContainer,
paginated_data_table::{PaginatedTable, PaginatedTableStateRx},
@ -42,6 +42,17 @@ fn index_page<G: Html>(cx: BoundedScope) -> View<G> {
table_class: table_classes,
};
let route_ref = create_ref(cx, move |c, p, s| {
api_scope_ref.get_major_transactions(c, p, s)
});
let table_transactions_major: PaginatedTableStateRx<MajorTransactions, _, _> =
PaginatedTableStateRx {
record_label: "transactions".to_owned(),
route: route_ref,
filter: Some((24 * 30).to_string()),
table_class: table_classes,
};
let dark_mode_class = create_memo(cx, || {
if *global_state.dark_mode.get() {
"dark"
@ -68,6 +79,12 @@ fn index_page<G: Html>(cx: BoundedScope) -> View<G> {
}
PaginatedTable(table_transactions_month)
}
div (class="flex-grow") {
h1 (class="mb-1 text-center") {
"Major transactions in the past 30 days"
}
PaginatedTable(table_transactions_major)
}
}
}
}

@ -80,6 +80,10 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
"/transaction/aggregated",
get(transaction::get_aggregated_transactions),
)
.route(
"/transaction/major",
get(transaction::get_recent_major_transactions),
)
.route(
"/in_process_transaction",
get(in_process_transaction::get_all),

@ -181,6 +181,71 @@ pub async fn get_aggregated_transactions(
Ok(Json(res))
}
#[derive(FromQueryResult, Serialize)]
pub struct MajorTransactions {
company_name: String,
slug: String,
date_published: NaiveDate,
date_executed: NaiveDate,
nature: String,
instrument: String,
volume: i32,
unit_price: f32,
total: f32,
}
pub async fn get_recent_major_transactions(
state: State<AppState>,
pagination: Query<Pagination>,
) -> Result<Json<PaginatedResponse<MajorTransactions>>, AppError> {
let db = &state.db;
let s = pagination.size.unwrap_or(20).min(50);
let query_raw = "SELECT
b.name as company_name,
b.slug,
date_published,
date_executed,
nature,
instrument,
volume,
unit_price,
volume * unit_price as total
FROM transaction a
JOIN company b
ON a.company_id = b.id
WHERE unit_price*volume > 1000000
AND created_at_utc > DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
ORDER BY a.nature, total DESC"
.to_string();
let query = model::transaction::Entity::find()
.from_raw_sql(Statement::from_string(
DbBackend::MySql,
query_raw.to_string(),
))
.into_model::<MajorTransactions>();
let pages = query.paginate(db, s);
let ItemsAndPagesNumber {
number_of_items: count,
number_of_pages: num_pages,
} = pages.num_items_and_pages().await?;
let p = pagination.page.unwrap_or(0).min(num_pages);
let list = pages.fetch_page(p).await?;
let res = PaginatedResponse {
count,
num_pages,
list,
};
Ok(Json(res))
}
#[derive(Serialize, FromQueryResult, Debug)]
pub struct TransactionsAggregated {
id: i32,

Loading…
Cancel
Save