| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- #[cfg(feature = "telegram")]
- use crate::categories::get_top_category;
- use crate::categories::CatStats;
- use crate::receipt;
- use crate::user::User;
- use chrono::{DateTime, Utc};
- use qif_generator::{account::Account, split::Split, transaction::Transaction};
- use std::fs;
- /// Read json file with receipt and convert it into `receipt::Purchase`
- pub fn read_file(f: &str) -> receipt::Purchase {
- let json = fs::read_to_string(f).expect(format!("Can't read file {}", f).as_str());
- receipt::parse_purchase(&json)
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use std::path::PathBuf;
- #[test]
- fn test_read_receipt() {
- let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- p.push("tests/resources/test.json");
- let full_path = p.to_string_lossy();
- let result = read_file(&full_path).items;
- assert_eq!(result[0].name, "СИДР 0.5 MAGNERS APP");
- assert_eq!(result[0].sum, 17713);
- }
- }
- /// Generate set of QIF Splits from a Purchase items
- pub fn gen_splits<F, C>(
- items: &[receipt::Item],
- cs: &mut CatStats,
- accounts: &[String],
- filter: F,
- categorizer: C,
- ) -> Vec<Split>
- where
- C: Fn(&str, &mut CatStats, &[String]) -> String,
- F: Fn(&str) -> &str,
- {
- let mut result: Vec<Split> = Vec::new();
- for i in items.iter() {
- let t = Split::new()
- .memo(filter(i.name.as_str()))
- .amount(-i.sum)
- .category(&categorizer(i.name.as_str(), cs, accounts))
- .build();
- result.push(t);
- }
- result
- }
- /// Generate QIF transaction from `splits`
- pub fn gen_trans<'a>(
- acc: &'a Account,
- date: DateTime<Utc>,
- sum: i64,
- memo: &str,
- splits: &[Split],
- ) -> Result<Transaction<'a>, String> {
- let t = Transaction::new(acc)
- .date(date)
- .memo(memo)
- .splits(splits)
- .build();
- match t {
- Ok(t) => {
- if t.sum() == -sum {
- Ok(t)
- } else {
- Err(format!(
- "Total sum is wrong. Expected: {} Got: {}",
- sum,
- t.sum()
- ))
- }
- }
- Err(e) => Err(e),
- }
- }
- /// Check if all items in `filename` do have a category assigned by `user`
- #[cfg(feature = "telegram")]
- pub fn non_cat_items(filename: &str, user: &User) -> Vec<String> {
- let file = read_file(filename);
- let mut result: Vec<String> = Vec::new();
- for i in file.items {
- match get_top_category(i.name.as_str(), &user.catmap) {
- Some(_) => (),
- None => result.push(String::from(i.name.as_str())),
- }
- }
- result
- }
- /// Convert `filename` into a QIF transaction
- pub fn convert<'a, F, C>(
- filename: &'a str,
- memo: &str,
- user: &'a mut User,
- acc: &'a Account,
- filter: F,
- categorizer: C,
- ) -> Result<Transaction<'a>, String>
- where
- F: Fn(&str) -> &str,
- C: Fn(&str, &mut CatStats, &[String]) -> String,
- {
- let purchase = &read_file(filename);
- let splits = &gen_splits(
- &purchase.items,
- &mut user.catmap,
- &user.accounts,
- &filter,
- &categorizer,
- );
- gen_trans(acc, purchase.date(), purchase.total_sum(), memo, splits)
- }
|