plm_rs/tables/
parts.rs

1extern crate diesel;
2
3use prettytable::{row, Table};
4use serde::Deserialize;
5
6use crate::{models::*, *};
7use diesel::prelude::*;
8
9use std::fs::File;
10use std::io::BufReader;
11
12#[derive(Debug, Deserialize)]
13struct Record {
14    pn: String,
15    mpn: String,
16    desc: String,
17}
18
19pub fn create(app: &mut crate::Application) {
20    // Get the input from stdin
21    let pn = app.prompt.ask_text_entry("Part Number: ");
22    let mpn = app.prompt.ask_text_entry("Manufacturer Part Number: ");
23    let desc = app.prompt.ask_text_entry("Description: ");
24    let ver = app.prompt.ask_text_entry("Version: ");
25    let ver: i32 = ver.trim().parse().expect("Invalid version number!");
26
27    // Create the part
28    let part = NewUpdatePart {
29        pn: &pn,
30        mpn: &mpn,
31        descr: &desc,
32        ver: &ver,
33        mqty: &1,
34    };
35
36    let found = find_part_by_pn(&app.conn, &pn);
37
38    // If already found ask if it should be updated
39    if let Ok(found) = found {
40        let question = format!("{} already exists! Would you like to update it?", pn);
41        let update = app.prompt.ask_yes_no_question(&question);
42
43        // Update if they said yes.
44        if update {
45            update_part(&app.conn, &found.id, &part).expect("Unable to update part!");
46
47            // Check for success
48            println!("{} updated!", pn);
49        }
50    } else {
51        create_part(&app.conn, &part).expect("Unable to create part!");
52    }
53}
54
55pub fn rename(app: &mut crate::Application) {
56    // Get the input from stdin
57    let pn = app.prompt.ask_text_entry("Part Number: ");
58    let newpn = app.prompt.ask_text_entry("New Part Number: ");
59
60    rename_part(&app.conn, &pn, &newpn).expect("Unable to change pn");
61}
62
63pub fn create_by_csv(app: &mut crate::Application, filename: &str) {
64    // Open the file
65    let file = File::open(filename).unwrap();
66    let file = BufReader::new(file);
67
68    let mut records: Vec<Record> = Vec::new();
69
70    let mut rdr = csv::Reader::from_reader(file);
71
72    // TODO handle empty or malformed content a bit... better.
73    // TODO: handle invalid data that's not UTF8
74    for result in rdr.deserialize() {
75        // Notice that we need to provide a type hint for automatic
76        // deserialization.
77        let record: Record = result.expect("Unable to deserialize.");
78        println!("Processing: {:?}", record);
79        records.push(record);
80    }
81
82    // Iterate through all the records.
83    for record in records {
84        // Create a new part from the CSV file
85        let part = models::NewUpdatePart {
86            pn: &record.pn,
87            mpn: &record.mpn,
88            descr: &record.desc,
89            ver: &1,
90            mqty: &1,
91        };
92
93        let found = find_part_by_pn(&app.conn, &part.pn);
94
95        // If already found ask if it should be updated
96        if let Ok(found) = found {
97            // Compare the two make sure they're different
98            if found.mpn != part.mpn || found.descr != part.descr || found.ver != *part.ver {
99                let question = format!("{} already exists! Would you like to update it?", part.pn);
100
101                // Create the table
102                let mut table = Table::new();
103                table.add_row(row![
104                    "Current:",
105                    found.pn,
106                    found.mpn,
107                    found.descr,
108                    found.ver
109                ]);
110                table.add_row(row!["Change to:", part.pn, part.mpn, part.descr, part.ver]);
111                table.printstd();
112
113                let update = app.prompt.ask_yes_no_question(&question);
114
115                // Update if they said yes.
116                if update {
117                    update_part(&app.conn, &found.id, &part).expect("Unable to update part!");
118
119                    // Check for success
120                    println!("{} updated!", part.pn);
121                }
122            }
123        } else {
124            println!("Creating: {:?}", part);
125            create_part(&app.conn, &part).expect("Unable to create part!");
126        }
127    }
128}
129
130pub fn delete(app: &mut crate::Application) {
131    let part = app.prompt.ask_text_entry("Part Number: ");
132
133    // First find the parts.
134    let part = find_part_by_pn(&app.conn, &part).expect("Unable to find part!");
135
136    // Then ask the user to confirm they want to delete
137    let question = format!("Would you like to delete {}?", part.pn);
138    let delete = app.prompt.ask_yes_no_question(&question);
139
140    // THEN, delete if they said yes.
141    if delete {
142        // Delete the part
143        let res = delete_part(&app.conn, &part.id);
144
145        // Depending on the result show the feedback
146        if res.is_err() {
147            panic!("Error deleting part {}.", part.pn);
148        } else {
149            println!("Deleted {}", part.pn);
150        }
151    }
152}
153
154pub fn show(app: &mut crate::Application) {
155    use crate::schema::*;
156
157    // Create the table
158    let mut table = Table::new();
159
160    let results = parts::dsl::parts
161        .load::<models::Part>(&app.conn)
162        .expect("Error loading parts");
163
164    println!("Displaying {} parts", results.len());
165    table.add_row(row!["PN", "MPN", "Desc", "Mqty", "Ver"]);
166    for part in results {
167        table.add_row(row![part.pn, part.mpn, part.descr, part.mqty, part.ver]);
168    }
169    table.printstd();
170}
171
172// pub fn search() {
173//   // TODO: use a partial/pattern to search
174//   // TODO: default is to search by PN but options to search by mpn, desc, etc.
175// }