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
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct VoteOptions(pub HashMap<String, u8>);

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct Proposal {
    #[serde(alias = "internalId")]
    pub internal_id: i32,
    #[serde(alias = "proposalId")]
    pub proposal_id: String,
    #[serde(alias = "proposalTitle")]
    pub proposal_title: String,
    #[serde(alias = "proposalFunds")]
    pub proposal_funds: i64,
    #[serde(alias = "proposalUrl")]
    pub proposal_url: String,
    #[serde(alias = "proposalImpactScore")]
    pub proposal_impact_score: i64,
    #[serde(alias = "chainProposalId")]
    pub chain_proposal_id: Vec<u8>,
    #[serde(alias = "chainVoteOptions")]
    pub chain_vote_options: VoteOptions,
    #[serde(alias = "challengeId")]
    pub challenge_id: i32,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct ProposalVotePlanCommon {
    #[serde(alias = "chainVoteplanId")]
    pub chain_voteplan_id: String,
    #[serde(alias = "chainProposalIndex")]
    pub chain_proposal_index: i64,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct FullProposalInfo {
    #[serde(flatten)]
    pub proposal: Proposal,
    #[serde(flatten)]
    pub voteplan: ProposalVotePlanCommon,
    #[serde(alias = "groupId")]
    pub group_id: String,
}

#[cfg(any(test, feature = "test-api"))]
impl From<vit_servicing_station_lib::db::models::proposals::FullProposalInfo> for FullProposalInfo {
    fn from(val: vit_servicing_station_lib::db::models::proposals::FullProposalInfo) -> Self {
        Self {
            proposal: Proposal {
                internal_id: val.proposal.internal_id,
                proposal_id: val.proposal.proposal_id,
                proposal_title: val.proposal.proposal_title,
                proposal_funds: val.proposal.proposal_funds,
                proposal_url: val.proposal.proposal_url,
                proposal_impact_score: val.proposal.proposal_impact_score,
                chain_proposal_id: val.proposal.chain_proposal_id,
                chain_vote_options: VoteOptions(val.proposal.chain_vote_options.0),
                challenge_id: val.proposal.challenge_id,
            },
            voteplan: ProposalVotePlanCommon {
                chain_voteplan_id: val.voteplan.chain_voteplan_id,
                chain_proposal_index: val.voteplan.chain_proposal_index,
            },
            group_id: val.group_id,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn proposal_json_test() {
        let json = serde_json::json!({
            "internal_id": 1,
            "proposal_id": "1",
            "proposal_title": "test",
            "proposal_funds": 1,
            "proposal_url": "test",
            "proposal_impact_score": 1,
            "chain_proposal_id": [1],
            "chain_vote_options": {
                "1": 1
            },
            "challenge_id": 1,
            "not_proposal_data": "some",
        });

        let proposal: Proposal = serde_json::from_value(json).unwrap();

        assert_eq!(
            proposal,
            Proposal {
                internal_id: 1,
                proposal_id: "1".to_string(),
                proposal_title: "test".to_string(),
                proposal_funds: 1,
                proposal_url: "test".to_string(),
                proposal_impact_score: 1,
                chain_proposal_id: vec![1],
                chain_vote_options: VoteOptions(HashMap::from([("1".to_string(), 1)])),
                challenge_id: 1
            }
        );
    }
}