From 01b9145978d4bee1e35e309b7680964da425d81b Mon Sep 17 00:00:00 2001
From: LastExceed <chris20194@googlemail.com>
Date: Thu, 20 Mar 2025 13:06:39 +0100
Subject: [PATCH] add billing log

---
 src/utils/logs.rs         |   6 +++
 src/utils/logs/billing.rs | 109 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 src/utils/logs/billing.rs

diff --git a/src/utils/logs.rs b/src/utils/logs.rs
index 202719e..53d0b29 100644
--- a/src/utils/logs.rs
+++ b/src/utils/logs.rs
@@ -9,6 +9,10 @@ use serde::Serialize;
 
 use crate::utils::booking::Booking;
 
+use self::billing::billinglog;
+
+mod billing;
+
 #[derive(Debug, Serialize)]
 struct Record<'s> {
     machine: &'s str,
@@ -21,6 +25,8 @@ struct Record<'s> {
 }
 
 pub fn machinelog(machine: &str, booking: &Booking) -> io::Result<()> {
+    billinglog(machine, booking)?;
+
     let record = Record {
         machine,
         date: booking.creation_datetime.date_naive().to_string(),
diff --git a/src/utils/logs/billing.rs b/src/utils/logs/billing.rs
new file mode 100644
index 0000000..dd5bd37
--- /dev/null
+++ b/src/utils/logs/billing.rs
@@ -0,0 +1,109 @@
+use std::{io, ops::Div};
+use std::collections::HashMap;
+use std::fs;
+use std::fs::File;
+
+use chrono::Local;
+use colour::red_ln;
+use csv::WriterBuilder;
+use lazy_static::lazy_static;
+use serde::Serialize;
+
+use crate::utils::booking::Booking; 
+
+struct MachineData {
+    id: i32,
+    to_be_used: bool,
+    power_sense: bool,
+    divider: i32
+}
+
+lazy_static! {
+    static ref DATA_USER: HashMap<String, String> = fs::read_to_string("DataUser.csv")
+        .expect("failed to open DataUser.csv")
+        .lines()
+        .map(|line| {
+            let (name, id) = line
+                .split_once(',')
+                .unwrap();
+            
+            (
+                name.to_string(),
+                id.to_string()
+            )
+        })
+        .collect();
+    static ref DATA_MACHINES: HashMap<String, MachineData> = fs::read_to_string("DataMachines.csv")
+        .expect("failed to open DataMachines.csv")
+        .lines()
+        .map(|line| {
+            let mut splits = line.split(',');
+            
+            let name = splits.next().unwrap().to_string();
+            let md = MachineData {
+                id         : splits.next().unwrap().parse       ().unwrap(),
+                to_be_used : splits.next().unwrap().parse::<i32>().unwrap() == 1,
+                power_sense: splits.next().unwrap().parse::<i32>().unwrap() == 1,
+                divider    : splits.next().unwrap().parse       ().unwrap()
+            };
+            
+            (name, md)
+        })
+        .collect();
+}
+
+#[derive(Debug, Serialize)]
+struct BillingRecord {
+    user_id: String,                      // id nachschlagen in DataUser.csv. Wenn Spalte 3 ("toBeUsed") == 0 dann skip. Wenn nicht vorhanden dann fallback zum Namen
+    quelle: &'static str,                 // "allgemeiner Beleg"
+    brutto_netto: i32,                    // 2
+    artikel_id: String,                      // DataMachine.csv#2
+    positionsdetails: String,             // Date
+    anzahl: i32,                          // minutes divided by DataMachine.csv#5 (ceil)
+    rechnungstyp: i32                     // 0
+}
+
+pub fn billinglog(machine: &str, booking: &Booking) -> io::Result<()> {
+    let machine_data = &DATA_MACHINES
+        .get(&machine.to_string());
+    
+    if !machine_data.is_some_and(|md| !md.to_be_used) {
+        return Ok(());
+    }
+    
+    let bill = BillingRecord {
+        user_id: DATA_USER
+            .get(&booking.user)
+            .unwrap_or(&booking.user)
+            .clone(),
+        quelle: "allgemeiner Beleg",
+        brutto_netto: 2,
+        artikel_id: machine_data
+            .map(|md| md.id.to_string())
+            .unwrap_or(machine.to_string()),
+        positionsdetails: Local::now()
+            .format("%Y-%m-%d")
+            .to_string(),
+        anzahl: booking
+            .total_runtime()
+            .as_secs_f32()
+            .div(60.0)
+            .ceil()
+            as _,
+        rechnungstyp: 0,
+    };
+    
+    let file_writer = File::options()
+        .create(true)
+        .append(true)
+        .open("/root/billinglog.csv")?;
+
+    WriterBuilder::new()
+        .has_headers(false)
+        .from_writer(file_writer)
+        .serialize(&bill)
+        .map_err(|error| {
+            red_ln!("error while serializing: {error}\n{bill:#?}");
+            io::ErrorKind::Other.into()
+        })
+}
\ No newline at end of file