Files

7.5 KiB

use actix_web::web::Data;
use chrono::{Datelike, DateTime, Timelike, Utc};
use futures::executor::block_on;
use sqlx::{Arguments, Pool, Row, Sqlite};
use sqlx::sqlite::{SqliteArguments, SqliteRow};

use common::models::production::Production;
use common::models::used::Used;

use crate::traits::database::{Database, DatabaseSub};
use crate::traits::query::QuerySub;
use crate::traits::standard::{Standard, StandardSub};

impl Standard for Production {
fn table_name() -> String {
"production".to_string()
}
}

impl StandardSub for Production {
fn parent_table() -> String {
"produced_entry_id".to_string()
}
}

impl QuerySub for Production {
fn from_sqlite_row(row: SqliteRow, _parent_id: i64, pool: &Data<Pool>) -> Production {
let production_id: i64 = row.get(0);

    let uses = Used::get_by_parent_id(production_id, pool);  

    Production {  
        id: production_id,  
        date_created: row.get(1),  
        date_produced: row.get(2),  
        mhd: row.get(3),  
        uses  
    }  
}  

fn from_sqlite_row_small(row: SqliteRow, _parent_id: i64, _pool: &Data<Pool<Sqlite>>) -> Production {  
    Production {  
        id: row.get(0),  
        date_created: row.get(1),  
        date_produced: row.get(2),  
        mhd: row.get(3),  
        uses: vec![]  
    }  
}  

}

impl DatabaseSub for Production {

}

impl Database for Production {
fn insert(&self, pool: &Data<Pool>) -> i64 {
// TODO: First check if there is enough from ingredient to produce

    let statement = format!(  
        "INSERT INTO {} (date_created) VALUES ($1)",  
        Production::table_name(),  
    );  

    let mut date_time: DateTime<Utc> = Utc::now();  
    date_time = date_time.with_day(21).unwrap();  
    date_time = date_time.with_month(09).unwrap();  
    //date_time = date_time.with_hour(10).unwrap();  

    let mut args = SqliteArguments::default();  
    args.add(date_time);  

    let mut conn = block_on(pool.acquire()).unwrap();  
    let temp = block_on(  
        sqlx::query_with(  
            statement.as_str(),  
            args)  
            .execute(&mut *conn)  
    );  

    println!("Produced result:\n {:#?}", temp);  

    // TODO: Check if problematic with more users when more productions are created in a very very short timespan.  
    let production_id = temp.unwrap().last_insert_rowid();  

    for entry in &self.uses {  
        let mut entry = entry.clone();  

        entry.production_id = Some(production_id);  
        entry.order_pos_id = None;  

        entry.insert(pool);  
    }  

    production_id  
}  

fn update(&self, pool: &Data<Pool<Sqlite>>) {  
    let production = Production::get_by_id(self.id, pool).first().unwrap().clone();  

    let mut date_produced: Option<DateTime<chrono::Utc>> = self.date_produced;  
    let mut mhd: Option<DateTime<chrono::Utc>> = self.mhd;  

    if production.date_produced.is_some() {  
        date_produced = production.date_produced;  
    }  

    if production.mhd.is_some() {  
        mhd = production.mhd;  
    }  

    let statement = format!(  
        "UPDATE {} SET date_produced = $2, mhd = $3 WHERE id = $1",  
        Production::table_name(),  
    );  

    let mut args = SqliteArguments::default();  
    args.add(&self.id);  
    args.add(date_produced);  
    args.add(mhd);  

    println!("Production");  

    let mut conn = block_on(pool.acquire()).unwrap();  
    let temp = block_on(  
        sqlx::query_with(  
            statement.as_str(),  
            args)  
            .execute(&mut *conn)  
    );  

    println!("Result:\n {:#?}", temp);  
}  

fn delete(&self, _pool: &Data<Pool<Sqlite>>) {  
    println!("Not allowed to delete!")  
}  

fn get_all(pool: &Data<Pool<Sqlite>>) -> Vec<Production> {  
    let mut conn = block_on(pool.acquire()).unwrap();  
    let res = block_on(  
        sqlx::query(format!("SELECT * FROM {}", Production::table_name()).as_str())  
            .fetch_all(&mut *conn)  
    );  
    conn.detach();  

    let mut productions: Vec<Production> = Vec::new();  

    match res {  
        Ok(records) => {  
            for record in records {  
                productions.push(  
                    // TODO: Load parent_id  
                    //Production::from_sqlite_row(record, -1, pool)                        Production::from_sqlite_row_small(record, -1, pool)  
                );  
            }  
        }  
        Err(err) => {  
            println!("Error while loading all production entries:");  
            println!("{:#?}", err);  
        }  
    }  

    productions  
}  

fn get_by_id(id: i64, pool: &Data<Pool<Sqlite>>) -> Vec<Production> {  
    let statement = format!(  
        "SELECT * FROM {} WHERE id = $1",  
        Production::table_name(),  
    );  

    let mut args = SqliteArguments::default();  
    args.add(id);  

    let mut conn = block_on(pool.acquire()).unwrap();  
    let res = block_on(  
        sqlx::query_with(  
            statement.as_str(),  
            args)  
            .fetch_all(&mut *conn)  
    );  
    conn.detach();  

    let mut productions: Vec<Production> = Vec::new();  

    match res {  
        Ok(records) => {  
            for record in records {  
                productions.push(  
                    // TODO: Load parent_id  
                    Production::from_sqlite_row(record, -1, pool)  
                    //Production::from_sqlite_row_small(record, -1, pool)  
                );  
            }  
        }  
        Err(err) => {  
            println!("Error while loading production with id: {}:", id);  
            println!("{:#?}", err);  
        }  
    }  

    productions  
}  

fn get_by_search(search_term: String, pool: &Data<Pool<Sqlite>>) -> Vec<Production> {  
    let statement = format!(  
        "SELECT * FROM {} WHERE description like \"%{}%\"",  
        Production::table_name(),  
        search_term,  
    );  

    let mut conn = block_on(pool.acquire()).unwrap();  
    let res = block_on(  
        sqlx::query(  
            statement.as_str())  
            .fetch_all(&mut *conn)  
    );  
    conn.detach();  

    let mut productions: Vec<Production> = Vec::new();  

    match res {  
        Ok(records) => {  
            for record in records {  
                productions.push(  
                    // TODO: Load parent_id  
                    //Production::from_sqlite_row(record, -1, pool)                        Production::from_sqlite_row_small(record, -1, pool)  
                );  
            }  
        }  
        Err(err) => {  
            println!("Error while loading variants with search term: {}:", search_term);  
            println!("{:#?}", err);  
        }  
    }  

    productions  
}  

}