refactor: apply clippy suggestions
This commit is contained in:
parent
edb5d6a372
commit
700ba180b6
7 changed files with 32 additions and 86 deletions
|
@ -221,6 +221,7 @@ impl AuthentifiedClient {
|
||||||
Ok(res.status() == 200)
|
Ok(res.status() == 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub async fn get_user_details(&self) -> Result<serde_json::Value> {
|
pub async fn get_user_details(&self) -> Result<serde_json::Value> {
|
||||||
let res = self.client
|
let res = self.client
|
||||||
.get(self.config.base_url.join("agg/user")?)
|
.get(self.config.base_url.join("agg/user")?)
|
||||||
|
@ -340,6 +341,7 @@ struct FormAnswer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Organization {
|
impl Organization {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub async fn get_details(&self) -> Result<serde_json::Value> {
|
pub async fn get_details(&self) -> Result<serde_json::Value> {
|
||||||
let details = self.client.simple_fetch(format!("organizations/{}", self.slug)).await?;
|
let details = self.client.simple_fetch(format!("organizations/{}", self.slug)).await?;
|
||||||
Ok(details)
|
Ok(details)
|
||||||
|
|
45
src/main.rs
45
src/main.rs
|
@ -89,45 +89,6 @@ fn load_user_cache() -> Result<UserCache, LoadError> {
|
||||||
Ok(cache)
|
Ok(cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find a better way to have the logic implemented
|
|
||||||
async fn get_auth_client_from_cache(
|
|
||||||
user_cache: &mut UserCache,
|
|
||||||
ha_client: &mut helloasso::Client,
|
|
||||||
login_payload: helloasso::LoginPayload
|
|
||||||
) -> Result<helloasso::AuthentifiedClient> {
|
|
||||||
|
|
||||||
async fn login(
|
|
||||||
user_cache: &mut UserCache,
|
|
||||||
ha_client: &mut helloasso::Client,
|
|
||||||
login_payload: helloasso::LoginPayload
|
|
||||||
) -> Result<helloasso::AuthentifiedClient> {
|
|
||||||
let auth_client = ha_client.login(
|
|
||||||
login_payload
|
|
||||||
).await.context("Failed to login")?;
|
|
||||||
user_cache.helloasso_session = Some(auth_client.session.clone());
|
|
||||||
write_user_cache(&user_cache).expect("unable to write user cache");
|
|
||||||
println!("Logged in and wrote token to cache");
|
|
||||||
Ok(auth_client)
|
|
||||||
}
|
|
||||||
|
|
||||||
match &user_cache.helloasso_session {
|
|
||||||
Some(cached_session) => {
|
|
||||||
let auth_client = ha_client.authentified_client(cached_session.clone());
|
|
||||||
|
|
||||||
if !auth_client.verify_auth().await? {
|
|
||||||
println!("Need to relog, token invalid");
|
|
||||||
return login(user_cache, ha_client, login_payload).await
|
|
||||||
}
|
|
||||||
println!("Used anterior token");
|
|
||||||
Ok(auth_client)
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
println!("First time login");
|
|
||||||
login(user_cache, ha_client, login_payload).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_proxy_from_url(proxy_url: &Option<String>) -> Result<Option<reqwest::Proxy>> {
|
fn get_proxy_from_url(proxy_url: &Option<String>) -> Result<Option<reqwest::Proxy>> {
|
||||||
Ok(match proxy_url {
|
Ok(match proxy_url {
|
||||||
Some(p) => Some(reqwest::Proxy::all(p)
|
Some(p) => Some(reqwest::Proxy::all(p)
|
||||||
|
@ -140,7 +101,7 @@ async fn launch_adapter(source: SourceType, config: &Config) -> Result<()> {
|
||||||
|
|
||||||
let mut user_cache = load_user_cache().context("Failed to load user cache")?;
|
let mut user_cache = load_user_cache().context("Failed to load user cache")?;
|
||||||
|
|
||||||
if !&config.paheko_base_url.ends_with("/") {
|
if !&config.paheko_base_url.ends_with('/') {
|
||||||
return Err(anyhow!("Invalid paheko base_url, it must end with a slash"))
|
return Err(anyhow!("Invalid paheko base_url, it must end with a slash"))
|
||||||
}
|
}
|
||||||
let mut paheko_client: paheko::Client = paheko::Client::new(paheko::ClientConfig {
|
let mut paheko_client: paheko::Client = paheko::Client::new(paheko::ClientConfig {
|
||||||
|
@ -156,8 +117,8 @@ async fn launch_adapter(source: SourceType, config: &Config) -> Result<()> {
|
||||||
let paheko_client: paheko::AuthentifiedClient = paheko_client.login(paheko_credentials).await?;
|
let paheko_client: paheko::AuthentifiedClient = paheko_client.login(paheko_credentials).await?;
|
||||||
|
|
||||||
match source {
|
match source {
|
||||||
SourceType::Csv => sync_csv::sync_csv(&paheko_client, &config, &mut user_cache).await?,
|
SourceType::Csv => sync_csv::sync_csv(&paheko_client, config, &mut user_cache).await?,
|
||||||
SourceType::Helloasso => sync_helloasso::sync_helloasso(&paheko_client, &config, &mut user_cache).await?
|
SourceType::Helloasso => sync_helloasso::sync_helloasso(&paheko_client, config, &mut user_cache).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -313,12 +313,12 @@ impl AuthentifiedClient {
|
||||||
Ok(ids.get(0).map(|x| x.id).unwrap_or(1)+1)
|
Ok(ids.get(0).map(|x| x.id).unwrap_or(1)+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_transactions(&self, id_years: &Vec<u32>)
|
pub async fn get_transactions(&self, id_years: &[u32])
|
||||||
-> Result<Vec<SimpleTransaction>>
|
-> Result<Vec<SimpleTransaction>>
|
||||||
{
|
{
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Row {
|
struct Row {
|
||||||
id: u64,
|
_id: u64,
|
||||||
label: String,
|
label: String,
|
||||||
reference: String,
|
reference: String,
|
||||||
#[serde(deserialize_with = "deserialize_json_list")]
|
#[serde(deserialize_with = "deserialize_json_list")]
|
||||||
|
@ -566,7 +566,7 @@ impl AuthentifiedClient {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_paheko_err(&self, err_response: reqwest::Response) -> () {
|
async fn show_paheko_err(&self, err_response: reqwest::Response) {
|
||||||
eprintln!("Paheko error details: {:?} {:?}", err_response.status(), err_response.text().await.unwrap())
|
eprintln!("Paheko error details: {:?} {:?}", err_response.status(), err_response.text().await.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ fn process_csv_value(value: String) -> Option<String> {
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
return Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_price(value: String) -> f64 {
|
fn process_price(value: String) -> f64 {
|
||||||
|
@ -33,7 +33,7 @@ fn process_price(value: String) -> f64 {
|
||||||
|
|
||||||
|
|
||||||
// read csv from stdin
|
// read csv from stdin
|
||||||
pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Config, user_cache: &mut UserCache) -> Result<()> {
|
pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Config, _user_cache: &mut UserCache) -> Result<()> {
|
||||||
// raw row record directly from CSV
|
// raw row record directly from CSV
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
struct AnswerRecord {
|
struct AnswerRecord {
|
||||||
|
@ -48,8 +48,6 @@ pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Confi
|
||||||
#[serde(rename = "Tarif")]
|
#[serde(rename = "Tarif")]
|
||||||
membership_mode: String,
|
membership_mode: String,
|
||||||
|
|
||||||
#[serde(rename = "Montant (€)")]
|
|
||||||
total_amount: String,
|
|
||||||
#[serde(rename = "Cotisation (€)")]
|
#[serde(rename = "Cotisation (€)")]
|
||||||
subscription_amount: String,
|
subscription_amount: String,
|
||||||
#[serde(rename = "Don (€)")]
|
#[serde(rename = "Don (€)")]
|
||||||
|
@ -83,14 +81,14 @@ pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Confi
|
||||||
for line_res in stdin.lock().lines() {
|
for line_res in stdin.lock().lines() {
|
||||||
let line = line_res.unwrap();
|
let line = line_res.unwrap();
|
||||||
eprintln!("{:?}",&line);
|
eprintln!("{:?}",&line);
|
||||||
if line.starts_with(",") {
|
if line.starts_with(',') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if line.contains(&"\\FIN_DES_DONNES") {
|
if line.contains("\\FIN_DES_DONNES") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
intermediate_inp.push_str(&line);
|
intermediate_inp.push_str(&line);
|
||||||
intermediate_inp.push_str("\n");
|
intermediate_inp.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rdr = ReaderBuilder::new()
|
let mut rdr = ReaderBuilder::new()
|
||||||
|
@ -107,8 +105,8 @@ pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Confi
|
||||||
let generalized_answer = GeneralizedAnswer {
|
let generalized_answer = GeneralizedAnswer {
|
||||||
first_name: Some(normalize_str(parsed_record.first_name)),
|
first_name: Some(normalize_str(parsed_record.first_name)),
|
||||||
last_name: normalize_str(parsed_record.last_name),
|
last_name: normalize_str(parsed_record.last_name),
|
||||||
email: process_csv_value(parsed_record.email).and_then(|s| EmailAddress::is_valid(&s).then(|| s)),
|
email: process_csv_value(parsed_record.email).and_then(|s| EmailAddress::is_valid(&s).then_some(s)),
|
||||||
phone: process_csv_value(parsed_record.phone).and_then(|s| parse_normalize_phone(s)),
|
phone: process_csv_value(parsed_record.phone).and_then(parse_normalize_phone),
|
||||||
skills: process_csv_value(parsed_record.skills),
|
skills: process_csv_value(parsed_record.skills),
|
||||||
address: process_csv_value(parsed_record.address)
|
address: process_csv_value(parsed_record.address)
|
||||||
.expect("Expected answer to have address"),
|
.expect("Expected answer to have address"),
|
||||||
|
@ -140,7 +138,6 @@ pub async fn sync_csv(paheko_client: &paheko::AuthentifiedClient, config: &Confi
|
||||||
sync_paheko(
|
sync_paheko(
|
||||||
paheko_client,
|
paheko_client,
|
||||||
config,
|
config,
|
||||||
user_cache,
|
|
||||||
generalized_answers,
|
generalized_answers,
|
||||||
CAISSE_ACCOUNT_CODE,
|
CAISSE_ACCOUNT_CODE,
|
||||||
"Papier"
|
"Papier"
|
||||||
|
|
|
@ -89,7 +89,7 @@ pub async fn sync_helloasso(paheko_client: &paheko::AuthentifiedClient, config:
|
||||||
let email = choose_email(&answer);
|
let email = choose_email(&answer);
|
||||||
|
|
||||||
// skip answers that were imported later and are stranger from helloasso
|
// skip answers that were imported later and are stranger from helloasso
|
||||||
let payment = answer.payments.iter().nth(0).expect("Expected payment to exists");
|
let payment = answer.payments.get(0).expect("Expected payment to exists");
|
||||||
if payment.extra == Some("Offline".to_string()) {
|
if payment.extra == Some("Offline".to_string()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -119,8 +119,6 @@ pub async fn sync_helloasso(paheko_client: &paheko::AuthentifiedClient, config:
|
||||||
birth_year: read_custom_field(&answer, HelloassoCustomFieldType::Birthday).and_then(parse_and_get_birthday_year),
|
birth_year: read_custom_field(&answer, HelloassoCustomFieldType::Birthday).and_then(parse_and_get_birthday_year),
|
||||||
inception_time: answer.order.inception_time,
|
inception_time: answer.order.inception_time,
|
||||||
reference: format!("HA/{}", answer.id),
|
reference: format!("HA/{}", answer.id),
|
||||||
// TODO: handle donation from helloasso, compare initial_amount and amount in payment
|
|
||||||
// or shareAmount
|
|
||||||
donation_amount,
|
donation_amount,
|
||||||
subscription_amount,
|
subscription_amount,
|
||||||
membership_mode: serde_json::from_value(serde_json::Value::String(answer.mode.clone()))
|
membership_mode: serde_json::from_value(serde_json::Value::String(answer.mode.clone()))
|
||||||
|
@ -141,7 +139,6 @@ pub async fn sync_helloasso(paheko_client: &paheko::AuthentifiedClient, config:
|
||||||
sync_paheko(
|
sync_paheko(
|
||||||
paheko_client,
|
paheko_client,
|
||||||
config,
|
config,
|
||||||
user_cache,
|
|
||||||
generalized_answers,
|
generalized_answers,
|
||||||
"512",
|
"512",
|
||||||
"HelloAsso"
|
"HelloAsso"
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use crate::paheko;
|
use crate::paheko;
|
||||||
use crate::paheko::{AccountingYear, SimpleTransaction};
|
use crate::paheko::{AccountingYear, SimpleTransaction};
|
||||||
use crate::{
|
use crate::Config;
|
||||||
Config, UserCache,
|
|
||||||
};
|
|
||||||
use crate::utils::{generate_id, normalize_first_name, normalize_last_name};
|
use crate::utils::{generate_id, normalize_first_name, normalize_last_name};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
@ -52,15 +50,16 @@ struct GeneralizedAnswer {
|
||||||
linked_user_first_name: Option<String>
|
linked_user_first_name: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_accounting_year_for_time<'a>(accounting_years: &'a Vec<AccountingYear>, time: &'a DateTime<Utc>) -> Option<&'a AccountingYear> {
|
fn get_accounting_year_for_time<'a>(
|
||||||
let date_ref = time.date_naive().clone();
|
accounting_years: &'a [AccountingYear], time: &'a DateTime<Utc>
|
||||||
|
) -> Option<&'a AccountingYear> {
|
||||||
|
let date_ref = time.date_naive();
|
||||||
accounting_years.iter().find(|year| year.start_date <= date_ref && date_ref <= year.end_date)
|
accounting_years.iter().find(|year| year.start_date <= date_ref && date_ref <= year.end_date)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sync_paheko(
|
pub async fn sync_paheko(
|
||||||
paheko_client: &paheko::AuthentifiedClient,
|
paheko_client: &paheko::AuthentifiedClient,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
user_cache: &mut UserCache,
|
|
||||||
answers: Vec<GeneralizedAnswer>,
|
answers: Vec<GeneralizedAnswer>,
|
||||||
debit_account_code: &str,
|
debit_account_code: &str,
|
||||||
via_name: &str
|
via_name: &str
|
||||||
|
@ -162,10 +161,8 @@ pub async fn sync_paheko(
|
||||||
if
|
if
|
||||||
existing_user_opt.is_some() &&
|
existing_user_opt.is_some() &&
|
||||||
existing_subscriptions.iter()
|
existing_subscriptions.iter()
|
||||||
.find(|membership| membership.users_ids
|
.any(|membership| membership.users_ids.iter().any(|i| *i == pk_user_summary.id))
|
||||||
.iter().find(|i| **i == pk_user_summary.id).is_some()
|
{
|
||||||
)
|
|
||||||
.is_some() {
|
|
||||||
eprintln!(" User is already subscribed to this activity");
|
eprintln!(" User is already subscribed to this activity");
|
||||||
} else {
|
} else {
|
||||||
// add activity for first member
|
// add activity for first member
|
||||||
|
@ -249,7 +246,7 @@ pub async fn sync_paheko(
|
||||||
// the linked_services, depend on a patch to paheko API code to work (see https://forge.lefuturiste.fr/mbess/paheko-fork/commit/a4fdd816112f51db23a2b02ac160b0513a5b09c5)
|
// the linked_services, depend on a patch to paheko API code to work (see https://forge.lefuturiste.fr/mbess/paheko-fork/commit/a4fdd816112f51db23a2b02ac160b0513a5b09c5)
|
||||||
linked_subscriptions: pk_user_service_registrations.iter().map(|x| x.id.clone()).collect()
|
linked_subscriptions: pk_user_service_registrations.iter().map(|x| x.id.clone()).collect()
|
||||||
};
|
};
|
||||||
let _ = paheko_client.register_transaction(transaction)
|
paheko_client.register_transaction(transaction)
|
||||||
.await.context("Expected to create new paheko transaction")?;
|
.await.context("Expected to create new paheko transaction")?;
|
||||||
stats.transaction_created += 1;
|
stats.transaction_created += 1;
|
||||||
eprintln!(" Created paheko transaction for subscription");
|
eprintln!(" Created paheko transaction for subscription");
|
||||||
|
@ -280,7 +277,7 @@ pub async fn sync_paheko(
|
||||||
linked_users: pk_users_summaries.iter().map(|x| x.id.clone()).collect(),
|
linked_users: pk_users_summaries.iter().map(|x| x.id.clone()).collect(),
|
||||||
linked_subscriptions: vec![]
|
linked_subscriptions: vec![]
|
||||||
};
|
};
|
||||||
let _ = paheko_client.register_transaction(transaction)
|
paheko_client.register_transaction(transaction)
|
||||||
.await.context("Expected to create new paheko transaction for donation")?;
|
.await.context("Expected to create new paheko transaction for donation")?;
|
||||||
stats.transaction_created += 1;
|
stats.transaction_created += 1;
|
||||||
eprintln!(" Created paheko transaction for donation");
|
eprintln!(" Created paheko transaction for donation");
|
||||||
|
|
22
src/utils.rs
22
src/utils.rs
|
@ -7,9 +7,9 @@ use chrono::prelude::{DateTime, Utc, NaiveDate, Datelike};
|
||||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Id(pub u64);
|
pub struct Id(pub u64);
|
||||||
|
|
||||||
impl Into<String> for Id {
|
impl From<Id> for String {
|
||||||
fn into(self) -> String {
|
fn from(val: Id) -> Self {
|
||||||
format!("{:x}", self.0)
|
format!("{:x}", val.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl fmt::Display for Id {
|
impl fmt::Display for Id {
|
||||||
|
@ -23,14 +23,6 @@ pub fn generate_id() -> Id {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_datetime(inp: &str) -> Option<DateTime<Utc>> {
|
|
||||||
let date = NaiveDate::parse_from_str(inp, "%d/%m/%Y").ok()?;
|
|
||||||
Some(DateTime::<Utc>::from_naive_utc_and_offset(
|
|
||||||
date.and_hms_opt(0, 0, 0).unwrap(),
|
|
||||||
Utc
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_datetime_american(inp: &str) -> Option<DateTime<Utc>> {
|
pub fn parse_datetime_american(inp: &str) -> Option<DateTime<Utc>> {
|
||||||
let date = NaiveDate::parse_from_str(inp, "%m/%d/%Y").ok()?;
|
let date = NaiveDate::parse_from_str(inp, "%m/%d/%Y").ok()?;
|
||||||
Some(DateTime::<Utc>::from_naive_utc_and_offset(
|
Some(DateTime::<Utc>::from_naive_utc_and_offset(
|
||||||
|
@ -60,7 +52,7 @@ pub fn complete_date(inp: NaiveDate) -> DateTime<Utc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalize_str(subject: String) -> String {
|
pub fn normalize_str(subject: String) -> String {
|
||||||
subject.trim().replace("\n", ";").to_string()
|
subject.trim().replace('\n', ";").to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// remove year precision to comply with GDPR eu rules
|
/// remove year precision to comply with GDPR eu rules
|
||||||
|
@ -81,9 +73,9 @@ pub fn capitalize(s: &str) -> String {
|
||||||
pub fn normalize_first_name(subject: String) -> String {
|
pub fn normalize_first_name(subject: String) -> String {
|
||||||
subject
|
subject
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
.replace(" ", "-")
|
.replace(' ', "")
|
||||||
.split("-")
|
.split('-')
|
||||||
.map(|x| capitalize(x))
|
.map(capitalize)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("-")
|
.join("-")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue