Skip to main content

mollendorff_forge/cli/commands/
results.rs

1//! Structured result types for CLI commands
2//!
3//! These types capture computation results that were previously only printed.
4//! Used by both CLI (format & print) and MCP server (serialize to JSON).
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9/// Result of the validate command
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ValidationResult {
12    pub tables_valid: bool,
13    pub scalars_valid: bool,
14    pub table_count: usize,
15    pub scalar_count: usize,
16    pub mismatches: Vec<ValidationMismatch>,
17}
18
19/// A single value mismatch found during validation
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ValidationMismatch {
22    pub name: String,
23    pub current_value: f64,
24    pub expected_value: f64,
25    pub diff: f64,
26}
27
28/// Result of the calculate command
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct CalculationResult {
31    pub tables: HashMap<String, TableSummary>,
32    pub scalars: HashMap<String, Option<f64>>,
33    pub unit_warnings: Vec<String>,
34    pub file_updated: bool,
35    pub dry_run: bool,
36}
37
38/// Summary of a calculated table
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct TableSummary {
41    pub name: String,
42    pub column_count: usize,
43    pub row_count: usize,
44    pub columns: Vec<String>,
45}
46
47/// Result of the audit command
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct AuditResult {
50    pub variable: String,
51    pub var_type: String,
52    pub current_value: Option<f64>,
53    pub calculated_value: Option<f64>,
54    pub formula: Option<String>,
55    pub dependencies: Vec<AuditDep>,
56    pub is_valid: bool,
57}
58
59/// Serializable dependency info (mirrors `AuditDependency` with Serialize)
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct AuditDep {
62    pub name: String,
63    pub dep_type: String,
64    pub formula: Option<String>,
65    pub value: Option<f64>,
66    pub children: Vec<Self>,
67}
68
69/// Result of the export command
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct ExportResult {
72    pub input_path: String,
73    pub output_path: String,
74    pub table_count: usize,
75    pub scalar_count: usize,
76}
77
78/// Result of an in-memory (buffer) export — returned when no `excel_path` is given
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct ExportBufferResult {
81    pub table_count: usize,
82    pub scalar_count: usize,
83    /// Base64-encoded .xlsx file content
84    pub excel_base64: String,
85    /// Size of the raw Excel file in bytes
86    pub byte_count: usize,
87}
88
89/// Result of the import command
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ImportResult {
92    pub input_path: String,
93    pub output_path: String,
94    pub table_count: usize,
95    pub scalar_count: usize,
96    pub mode: String,
97}
98
99/// Result of sensitivity analysis
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct SensitivityResult {
102    pub vary: String,
103    pub output: String,
104    pub data: SensitivityData,
105}
106
107/// Sensitivity data — one-variable or two-variable
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum SensitivityData {
110    OneVar {
111        entries: Vec<SensitivityEntry>,
112    },
113    TwoVar {
114        vary2: String,
115        row_values: Vec<f64>,
116        col_values: Vec<f64>,
117        matrix: Vec<Vec<Option<f64>>>,
118    },
119}
120
121/// A single point in 1D sensitivity analysis
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct SensitivityEntry {
124    pub input: f64,
125    pub output: Option<f64>,
126    pub error: Option<String>,
127}
128
129/// Result of goal-seek (also used for break-even)
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct GoalSeekResult {
132    pub vary: String,
133    pub target: String,
134    pub target_value: f64,
135    pub solution: f64,
136    pub achieved: f64,
137    pub error: f64,
138    pub iterations: i32,
139    pub converged: bool,
140}
141
142/// Result of variance analysis
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct VarianceAnalysis {
145    pub results: Vec<VarianceEntry>,
146    pub favorable_count: usize,
147    pub unfavorable_count: usize,
148    pub alert_count: usize,
149    pub threshold: f64,
150}
151
152/// A single variance entry (serializable version of `VarianceResult`)
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct VarianceEntry {
155    pub name: String,
156    pub budget: f64,
157    pub actual: f64,
158    pub variance: f64,
159    pub variance_pct: f64,
160    pub is_favorable: bool,
161    pub exceeds_threshold: bool,
162}
163
164/// Result of scenario comparison
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct ComparisonResult {
167    pub scenarios: Vec<String>,
168    pub variables: Vec<String>,
169    pub values: HashMap<String, HashMap<String, Option<f64>>>,
170}