Compare commits

...

2 commits

8 changed files with 86 additions and 15 deletions

10
Cargo.lock generated
View file

@ -1562,6 +1562,7 @@ dependencies = [
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"serde_variant",
"strsim 0.11.0", "strsim 0.11.0",
"strum 0.25.0", "strum 0.25.0",
"surf", "surf",
@ -2085,6 +2086,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_variant"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a0068df419f9d9b6488fdded3f1c818522cdea328e02ce9d9f147380265a432"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.6.1" version = "0.6.1"

View file

@ -27,3 +27,4 @@ csv = "1.3.0"
argh = "0.1.12" argh = "0.1.12"
strsim = "0.11.0" strsim = "0.11.0"
async-recursion = "1.0.5" async-recursion = "1.0.5"
serde_variant = "0.1.3"

View file

@ -1,5 +1,3 @@
#![feature(slice_group_by)]
mod utils; mod utils;
mod paheko; mod paheko;
mod helloasso; mod helloasso;

View file

@ -98,7 +98,9 @@ struct SimpleTransaction {
reference: Option<String>, reference: Option<String>,
linked_users: Vec<Id>, linked_users: Vec<Id>,
linked_subscriptions: Vec<Id>, linked_subscriptions: Vec<Id>,
accounting_year: Id accounting_year: Id,
payment_reference: Option<String>,
notes: Option<String>
} }
@ -360,6 +362,8 @@ impl AuthentifiedClient {
kind: TransactionKind::Expense, kind: TransactionKind::Expense,
linked_subscriptions: vec![], linked_subscriptions: vec![],
linked_users: vec![], linked_users: vec![],
payment_reference: None,
notes: None
}).collect()) }).collect())
} }
@ -397,9 +401,9 @@ impl AuthentifiedClient {
expiry_date: NaiveDate expiry_date: NaiveDate
} }
let intermidiate: Vec<Row> = serde_json::from_value(val.results)?; let intermidiate: Vec<Row> = serde_json::from_value(val.results)?;
// regroup the row with the same id // group the rows with the same id
Ok(intermidiate Ok(intermidiate
.group_by(|a,b| a.id == b.id) .chunk_by(|a,b| a.id == b.id)
.map(|rows| { .map(|rows| {
let base = rows.first().unwrap(); let base = rows.first().unwrap();
@ -547,8 +551,14 @@ impl AuthentifiedClient {
// "Numéro pièce comptable" enregistré au niveau de la transaction // "Numéro pièce comptable" enregistré au niveau de la transaction
; ;
if let Some(reference) = transaction.reference { if let Some(val) = transaction.reference {
form = form.text("reference", reference); form = form.text("reference", val);
}
if let Some(val) = transaction.payment_reference {
form = form.text("reference", val);
}
if let Some(val) = transaction.notes {
form = form.text("notes", val);
} }
for linked_id in transaction.linked_users { for linked_id in transaction.linked_users {
form = form.text("linked_users[]", format!("{}", linked_id.0)); form = form.text("linked_users[]", format!("{}", linked_id.0));

View file

@ -5,7 +5,7 @@ use crate::{
use anyhow::Result; use anyhow::Result;
use crate::utils::{normalize_str, parse_date_iso, parse_normalize_phone}; use crate::utils::{normalize_str, parse_date_iso, parse_normalize_phone};
use crate::sync_paheko::{GeneralizedAnswer, sync_paheko}; use crate::sync_paheko::{sync_paheko, GeneralizedAnswer, PaymentMode};
use email_address::EmailAddress; use email_address::EmailAddress;
use chrono::prelude::Datelike; use chrono::prelude::Datelike;
use std::io::BufRead; use std::io::BufRead;
@ -45,7 +45,7 @@ pub async fn sync_csv(
// Ref BP // Ref BP
reference: String, reference: String,
date: String, inception_date: String,
email: String, email: String,
first_name: String, first_name: String,
last_name: String, last_name: String,
@ -76,7 +76,7 @@ pub async fn sync_csv(
// Don (€) // Don (€)
donation_amount: String, donation_amount: String,
// Mode de paiement // Mode de paiement (Espèce or Cheque, ESP or CHQ)
payment_mode: String payment_mode: String
} }
@ -123,7 +123,7 @@ pub async fn sync_csv(
birth_year: process_csv_value(parsed_record.birth_date) birth_year: process_csv_value(parsed_record.birth_date)
.and_then(|raw_date| parse_date_iso(&raw_date)) .and_then(|raw_date| parse_date_iso(&raw_date))
.map(|d| d.year() as u32), .map(|d| d.year() as u32),
inception_time: process_csv_value(parsed_record.date) inception_time: process_csv_value(parsed_record.inception_date)
.map(|s| .map(|s|
parse_date_iso(&s).expect("Record must have a valid date") parse_date_iso(&s).expect("Record must have a valid date")
) )
@ -133,7 +133,16 @@ pub async fn sync_csv(
subscription_amount: process_price(parsed_record.subscription_amount), // FIXME: get subscription from mode subscription_amount: process_price(parsed_record.subscription_amount), // FIXME: get subscription from mode
membership_mode: serde_json::from_value(serde_json::Value::String(parsed_record.membership_mode.clone())) membership_mode: serde_json::from_value(serde_json::Value::String(parsed_record.membership_mode.clone()))
.expect("Expected a membership mode to be valid"), .expect("Expected a membership mode to be valid"),
linked_user_first_name: process_csv_value(parsed_record.linked_user_first_name) linked_user_first_name: process_csv_value(parsed_record.linked_user_first_name),
payment_mode: match process_csv_value(parsed_record.payment_mode) {
Some(payment_mode_name) => serde_json::from_str(
&format!(
"\"{}\"",
payment_mode_name.to_ascii_uppercase()
)
).expect("Could not parse payment mode"),
None => PaymentMode::Cheque
}
}; };
generalized_answers.push(generalized_answer); generalized_answers.push(generalized_answer);

View file

@ -1,5 +1,6 @@
use crate::helloasso; use crate::helloasso;
use crate::paheko; use crate::paheko;
use crate::sync_paheko::PaymentMode;
use crate::{ use crate::{
Config, UserCache, Config, UserCache,
get_proxy_from_url, write_user_cache get_proxy_from_url, write_user_cache
@ -168,7 +169,8 @@ pub async fn sync_helloasso(
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()))
.expect("Expected a membership mode to be valid"), .expect("Expected a membership mode to be valid"),
linked_user_first_name: read_custom_field(&answer, HelloassoCustomFieldType::LinkedUserFirstName) linked_user_first_name: read_custom_field(&answer, HelloassoCustomFieldType::LinkedUserFirstName),
payment_mode: PaymentMode::CreditCard
}; };
// apply custom user override // apply custom user override

View file

@ -24,6 +24,17 @@ enum MembershipMode {
BenefactorCouple, BenefactorCouple,
} }
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[fully_pub]
enum PaymentMode {
#[serde(rename = "ESP")]
Cash,
#[serde(rename = "CB")]
CreditCard,
#[serde(rename = "CHQ")]
Cheque
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[fully_pub] #[fully_pub]
struct GeneralizedAnswer { struct GeneralizedAnswer {
@ -46,6 +57,7 @@ struct GeneralizedAnswer {
subscription_amount: f64, subscription_amount: f64,
donation_amount: f64, donation_amount: f64,
reference: String, reference: String,
payment_mode: PaymentMode,
linked_user_first_name: Option<String> linked_user_first_name: Option<String>
} }
@ -244,7 +256,12 @@ pub async fn sync_paheko(
inception_time: answer.inception_time, inception_time: answer.inception_time,
kind: paheko::TransactionKind::Revenue, kind: paheko::TransactionKind::Revenue,
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: pk_user_service_registrations.iter().map(|x| x.id.clone()).collect() linked_subscriptions: pk_user_service_registrations.iter().map(|x| x.id.clone()).collect(),
payment_reference: serde_variant::to_variant_name(&answer.payment_mode)
.map(|x| x.to_string())
.ok(),
notes: serde_json::to_string(&answer.payment_mode)
.map(|x| format!("Mode de paiement: {}", x)).ok()
}; };
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")?;
@ -275,7 +292,12 @@ pub async fn sync_paheko(
inception_time: answer.inception_time, inception_time: answer.inception_time,
kind: paheko::TransactionKind::Revenue, kind: paheko::TransactionKind::Revenue,
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![],
payment_reference: serde_variant::to_variant_name(&answer.payment_mode)
.map(|x| x.to_string())
.ok(),
notes: serde_json::to_string(&answer.payment_mode)
.map(|x| format!("Mode de paiement: {}", x)).ok()
}; };
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")?;

View file

@ -1,4 +1,5 @@
use crate::utils::{normalize_str, normalize_first_name}; use crate::utils::{normalize_str, normalize_first_name};
use crate::sync_paheko::PaymentMode;
#[test] #[test]
fn test_normalize_str() { fn test_normalize_str() {
@ -25,3 +26,21 @@ fn test_normalize_first_name() {
assert_eq!(out, "Jeffrey"); assert_eq!(out, "Jeffrey");
} }
#[test]
fn test_parse_payment_mode() {
let tmp = "\"ESP\"".to_string().to_ascii_uppercase();
dbg!(&tmp);
assert_eq!(
serde_json::from_str::<PaymentMode>(&tmp).unwrap(),
PaymentMode::Cash
)
}
#[test]
fn test_payment_mode_to_string() {
assert_eq!(
serde_json::to_string(&PaymentMode::Cash).unwrap(),
"\"ESP\""
)
}