1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use {validate, Client, Result};
use db::{column, table};
use models::{Project, User};
use postgres::error::SqlState;
use rustorm::dao::{FromValue, Value};
use rustorm::database::{Database, DbError};
use rustorm::query::{Equality, Query};
use std::collections::BTreeMap;
use std::convert::From;
impl Project {
pub fn create(client: &Client, project_name: &str, amount: f64) -> Result<Project> {
try!(validate::length(project_name, 4, 20));
try!(validate::alphanumeric(project_name));
let amount = try!(validate::currency(amount));
let mut result = Query::insert()
.set(column::name, &project_name)
.set(column::goal, &amount)
.into_table(&client.table(table::project))
.return_all()
.collect_one(client.db());
Project::check_valid_errors(&mut result, project_name);
let project = try!(result);
Ok(project)
}
fn check_valid_errors(res: &mut ::std::result::Result<Project, DbError>, project_name: &str) {
let mut message = String::new();
if let &mut Err(ref err) = res {
if let Some(SqlState::UniqueViolation) = err.code {
message = format!("Project '{}' already exists!", project_name);
}
}
if !message.is_empty() {
*res = Err(DbError::with_code(&message, SqlState::UniqueViolation));
}
}
pub fn get_id(client: &Client, project_name: &str) -> Result<Value> {
let result = try!(Query::select()
.column(column::project_id)
.from_table(&client.table(table::project))
.filter(column::name, Equality::EQ, &project_name)
.retrieve(client.db()));
if result.dao.is_empty() {
Err(From::from(validate::Error::ProjectDoesNotExist))
} else {
let id = result.dao[0].values.get(column::project_id).unwrap();
Ok(id.clone())
}
}
pub fn list_all(client: &Client) -> Result<Vec<Project>> {
let results: Vec<Project> = try!(Query::select_all()
.from_table(&client.table(table::project))
.collect(client.db()));
Ok(results)
}
pub fn list_backers(client: &Client, project_name: &str) -> Result<(BTreeMap<User, f64>, f64)> {
let dao_results = try!(Query::select()
.column(&"us.*")
.column(&"pl.amount")
.column(&"pr.goal")
.from_table(&client.table_abbr(table::project))
.left_join_table(&client.table_abbr(table::pledge), &"pl.project_id", &"pr.project_id")
.left_join_table(&client.table_abbr(table::user), &"pl.user_id", &"us.user_id")
.filter(&"pr.name", Equality::EQ, &project_name)
.retrieve(client.db()));
if dao_results.dao.is_empty() {
return Err(From::from(validate::Error::ProjectDoesNotExist));
}
let goal = dao_results.dao[0].get_value(column::goal);
let mut results: BTreeMap<User, f64> = BTreeMap::new();
let mut users: Vec<User> = dao_results.cast();
for dao in dao_results.dao.iter().rev() {
let val = dao.get_value(column::amount);
if val != Value::Null {
let amount = FromValue::from_type(val);
results.insert(users.pop().unwrap(), amount);
}
}
Ok((results, FromValue::from_type(goal)))
}
}