From 05d2a969006c7a043f8edbd2e4cb0a460b18521e Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:27:15 -0500 Subject: [PATCH] Organization payouts (#848) --- ...2ccbbbccf2527c523336f230c0e344c471a0f.json | 35 +++++++++ src/queue/payouts.rs | 75 +++++++++++++------ src/routes/v2/projects.rs | 19 +++-- src/routes/v2/versions.rs | 2 +- 4 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 .sqlx/query-03cd8926d18aa8c11934fdc0da32ccbbbccf2527c523336f230c0e344c471a0f.json diff --git a/.sqlx/query-03cd8926d18aa8c11934fdc0da32ccbbbccf2527c523336f230c0e344c471a0f.json b/.sqlx/query-03cd8926d18aa8c11934fdc0da32ccbbbccf2527c523336f230c0e344c471a0f.json new file mode 100644 index 000000000..6671362ad --- /dev/null +++ b/.sqlx/query-03cd8926d18aa8c11934fdc0da32ccbbbccf2527c523336f230c0e344c471a0f.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT m.id id, tm.user_id user_id, tm.payouts_split payouts_split\n FROM mods m\n INNER JOIN organizations o ON m.organization_id = o.id\n INNER JOIN team_members tm on o.team_id = tm.team_id AND tm.accepted = TRUE\n WHERE m.id = ANY($1) AND m.monetization_status = $2 AND m.organization_id IS NOT NULL\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "user_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "payouts_split", + "type_info": "Numeric" + } + ], + "parameters": { + "Left": [ + "Int8Array", + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "03cd8926d18aa8c11934fdc0da32ccbbbccf2527c523336f230c0e344c471a0f" +} diff --git a/src/queue/payouts.rs b/src/queue/payouts.rs index 76b4fd2b1..917df20b5 100644 --- a/src/queue/payouts.rs +++ b/src/queue/payouts.rs @@ -520,8 +520,6 @@ pub async fn process_payout( redis: &RedisPool, client: &clickhouse::Client, ) -> Result<(), ApiError> { - return Ok(()); - let start: DateTime = DateTime::from_naive_utc_and_offset( (Utc::now() - Duration::days(1)) .date_naive() @@ -621,40 +619,69 @@ pub async fn process_payout( let mut projects_map: HashMap = HashMap::new(); - use futures::TryStreamExt; + let project_ids = multipliers + .values + .keys() + .map(|x| *x as i64) + .collect::>(); - sqlx::query!( + let project_org_members = sqlx::query!( + " + SELECT m.id id, tm.user_id user_id, tm.payouts_split payouts_split + FROM mods m + INNER JOIN organizations o ON m.organization_id = o.id + INNER JOIN team_members tm on o.team_id = tm.team_id AND tm.accepted = TRUE + WHERE m.id = ANY($1) AND m.monetization_status = $2 AND m.organization_id IS NOT NULL + ", + &project_ids, + MonetizationStatus::Monetized.as_str(), + ) + .fetch_all(&mut *transaction) + .await?; + + let project_team_members = sqlx::query!( " SELECT m.id id, tm.user_id user_id, tm.payouts_split payouts_split FROM mods m INNER JOIN team_members tm on m.team_id = tm.team_id AND tm.accepted = TRUE WHERE m.id = ANY($1) AND m.monetization_status = $2 ", - &multipliers - .values - .keys() - .map(|x| *x as i64) - .collect::>(), + &project_ids, MonetizationStatus::Monetized.as_str(), ) - .fetch_many(&mut *transaction) - .try_for_each(|e| { - if let Some(row) = e.right() { - if let Some(project) = projects_map.get_mut(&row.id) { - project.team_members.push((row.user_id, row.payouts_split)); - } else { - projects_map.insert( - row.id, - Project { - team_members: vec![(row.user_id, row.payouts_split)], - }, - ); + .fetch_all(&mut *transaction) + .await?; + + for project_id in project_ids { + let team_members: HashMap = project_team_members + .iter() + .filter(|r| r.id == project_id) + .map(|r| (r.user_id, r.payouts_split)) + .collect(); + let org_team_members: HashMap = project_org_members + .iter() + .filter(|r| r.id == project_id) + .map(|r| (r.user_id, r.payouts_split)) + .collect(); + + let mut all_team_members = vec![]; + + for (user_id, payouts_split) in org_team_members { + if !team_members.contains_key(&user_id) { + all_team_members.push((user_id, payouts_split)); } } + for (user_id, payouts_split) in team_members { + all_team_members.push((user_id, payouts_split)); + } - futures::future::ready(Ok(())) - }) - .await?; + projects_map.insert( + project_id, + Project { + team_members: all_team_members, + }, + ); + } let amount = Decimal::from(parse_var::("PAYOUTS_BUDGET").unwrap_or(0)); diff --git a/src/routes/v2/projects.rs b/src/routes/v2/projects.rs index 3cde37b39..6dbf1004a 100644 --- a/src/routes/v2/projects.rs +++ b/src/routes/v2/projects.rs @@ -94,12 +94,17 @@ pub async fn project_search( .into_iter() .map(|facet| { if let Some((key, operator, val)) = parse_facet(&facet) { - format!("{}{}{}", match key.as_str() { - "versions" => "game_versions", - "project_type" => "project_types", - "title" => "name", - x => x, - }, operator, val) + format!( + "{}{}{}", + match key.as_str() { + "versions" => "game_versions", + "project_type" => "project_types", + "title" => "name", + x => x, + }, + operator, + val + ) } else { facet.to_string() } @@ -127,7 +132,7 @@ pub async fn project_search( } /// Parses a facet into a key, operator, and value -fn parse_facet(facet: &String) -> Option<(String, String, String)> { +fn parse_facet(facet: &str) -> Option<(String, String, String)> { let mut key = String::new(); let mut operator = String::new(); let mut val = String::new(); diff --git a/src/routes/v2/versions.rs b/src/routes/v2/versions.rs index f2ca356dd..85e1c7fbf 100644 --- a/src/routes/v2/versions.rs +++ b/src/routes/v2/versions.rs @@ -247,7 +247,7 @@ pub async fn version_edit( // Get the older version to get info from let old_version = v3::versions::version_get_helper( req.clone(), - info.clone().0, + (*info).0, pool.clone(), redis.clone(), session_queue.clone(),