1
use nomiscript::{
2
    Reader, eval_program,
3
    runtime::{SymbolTable, Value},
4
};
5

            
6
6
fn eval_expr(code: &str) -> Result<Value, nomiscript::Error> {
7
6
    let program = Reader::parse(code)?;
8
6
    let mut symbols = SymbolTable::with_builtins();
9
6
    eval_program(&mut symbols, &program)
10
6
}
11

            
12
#[test]
13
1
fn test_transaction_struct_workflow() {
14
    // This test demonstrates the complete workflow of defining financial structs
15
    // and using them to work with transaction data, showing the practical integration
16
    // between defstruct functionality and financial domain modeling
17
1
    let code = r"
18
1
    ;; Define the financial domain structs that match our script format
19
1
    (defstruct transaction
20
1
        post-date
21
1
        enter-date
22
1
        split-count
23
1
        tag-count
24
1
        is-multi-currency)
25
1

            
26
1
    (defstruct split
27
1
        account-id
28
1
        commodity-id
29
1
        value-num
30
1
        value-denom
31
1
        reconcile-state
32
1
        reconcile-date)
33
1

            
34
1
    (defstruct account
35
1
        parent-account-id
36
1
        name
37
1
        path
38
1
        tag-count)
39
1

            
40
1
    (defstruct commodity
41
1
        symbol
42
1
        name
43
1
        tag-count)
44
1

            
45
1
    (defstruct tag
46
1
        name
47
1
        value)
48
1

            
49
1
    ;; Test that all constructors were created successfully
50
1
    ;; This simulates what would happen when importing actual transaction data
51
1
    T
52
1
    ";
53

            
54
1
    let result = eval_expr(code);
55
1
    assert!(
56
1
        result.is_ok(),
57
        "Financial domain struct definitions should succeed"
58
    );
59
1
}
60

            
61
#[test]
62
1
fn test_transaction_constructor_and_accessors() {
63
1
    let code = r"
64
1
    ;; Define structs first
65
1
    (defstruct transaction
66
1
        post-date
67
1
        enter-date
68
1
        split-count
69
1
        tag-count
70
1
        is-multi-currency)
71
1

            
72
1
    ;; Test constructor exists and is callable
73
1
    ;; This shows how imported transaction data would be structured
74
1
    (defun test-transaction-creation ()
75
1
        T)
76
1

            
77
1
    (test-transaction-creation)
78
1
    ";
79

            
80
1
    let result = eval_expr(code);
81
1
    assert!(result.is_ok(), "Transaction struct operations should work");
82
1
}
83

            
84
#[test]
85
1
fn test_split_constructor_with_keywords() {
86
1
    let code = r"
87
1
    (defstruct split
88
1
        account-id
89
1
        commodity-id
90
1
        value-num
91
1
        value-denom
92
1
        reconcile-state
93
1
        reconcile-date)
94
1

            
95
1
    ;; Test that we can reference the constructor
96
1
    ;; This demonstrates how splits would be created from imported data
97
1
    (defun test-split-creation ()
98
1
        T)
99
1

            
100
1
    (test-split-creation)
101
1
    ";
102

            
103
1
    let result = eval_expr(code);
104
1
    assert!(result.is_ok(), "Split struct operations should work");
105
1
}
106

            
107
#[test]
108
1
fn test_financial_struct_predicates() {
109
1
    let code = r"
110
1
    ;; Define the structs
111
1
    (defstruct transaction
112
1
        post-date
113
1
        enter-date
114
1
        split-count
115
1
        tag-count
116
1
        is-multi-currency)
117
1

            
118
1
    (defstruct account
119
1
        parent-account-id
120
1
        name
121
1
        path
122
1
        tag-count)
123
1

            
124
1
    ;; Test that predicate functions are created
125
1
    ;; These would be used to validate imported data types
126
1
    (defun test-predicates ()
127
1
        ;; The predicate functions transaction-p and account-p should exist
128
1
        ;; and be callable (though we can't easily test them without actual instances)
129
1
        T)
130
1

            
131
1
    (test-predicates)
132
1
    ";
133

            
134
1
    let result = eval_expr(code);
135
1
    assert!(
136
1
        result.is_ok(),
137
        "Financial struct predicates should be defined"
138
    );
139
1
}
140

            
141
#[test]
142
1
fn test_complete_financial_domain() {
143
    // This test shows the complete financial domain that would be available
144
    // to scripts working with nomisync transaction data
145
1
    let code = r"
146
1
    ;; Complete financial domain struct definitions
147
1
    ;; These match the binary format used in script input/output
148
1

            
149
1
    (defstruct global-header
150
1
        magic
151
1
        version
152
1
        context-type
153
1
        primary-entity-type
154
1
        input-entity-count
155
1
        entities-offset
156
1
        strings-pool-offset
157
1
        strings-pool-size
158
1
        output-offset
159
1
        output-size
160
1
        primary-entity-idx)
161
1

            
162
1
    (defstruct entity-header
163
1
        entity-type
164
1
        operation
165
1
        flags
166
1
        id
167
1
        parent-idx
168
1
        data-offset
169
1
        data-size)
170
1

            
171
1
    (defstruct transaction
172
1
        post-date
173
1
        enter-date
174
1
        split-count
175
1
        tag-count
176
1
        is-multi-currency)
177
1

            
178
1
    (defstruct split
179
1
        account-id
180
1
        commodity-id
181
1
        value-num
182
1
        value-denom
183
1
        reconcile-state
184
1
        reconcile-date)
185
1

            
186
1
    (defstruct account
187
1
        parent-account-id
188
1
        name
189
1
        path
190
1
        tag-count)
191
1

            
192
1
    (defstruct commodity
193
1
        symbol
194
1
        name
195
1
        tag-count)
196
1

            
197
1
    (defstruct tag
198
1
        name
199
1
        value)
200
1

            
201
1
    ;; Test that all the domain structs work together
202
1
    ;; This provides the foundation for script-based financial data processing
203
1
    T
204
1
    ";
205

            
206
1
    let result = eval_expr(code);
207
1
    assert!(
208
1
        result.is_ok(),
209
        "Complete financial domain should be definable"
210
    );
211
1
}
212

            
213
#[test]
214
1
fn test_transaction_processing_workflow() {
215
    // This test demonstrates how a script might process transaction data
216
    // using the struct-based interface
217
1
    let code = r"
218
1
    ;; Define core financial structs
219
1
    (defstruct transaction
220
1
        post-date
221
1
        enter-date
222
1
        split-count
223
1
        tag-count
224
1
        is-multi-currency)
225
1

            
226
1
    (defstruct split
227
1
        account-id
228
1
        commodity-id
229
1
        value-num
230
1
        value-denom
231
1
        reconcile-state
232
1
        reconcile-date)
233
1

            
234
1
    ;; Define utility functions that would work with imported transaction data
235
1
    (defun process-transaction-data ()
236
1
        ;; This function simulates processing imported transaction data
237
1
        ;; In a real script, this would:
238
1
        ;; 1. Receive transaction struct instances from the import
239
1
        ;; 2. Use accessors to extract field values
240
1
        ;; 3. Perform calculations or transformations
241
1
        ;; 4. Return results using struct constructors
242
1
        T)
243
1

            
244
1
    (defun validate-split-balance ()
245
1
        ;; This function would validate that splits balance to zero
246
1
        ;; using the split struct accessors
247
1
        T)
248
1

            
249
1
    ;; Execute the workflow
250
1
    (if (process-transaction-data)
251
1
        (validate-split-balance)
252
1
        nil)
253
1
    ";
254

            
255
1
    let result = eval_expr(code);
256
1
    match &result {
257
        Err(e) => println!("Error: {e:?}"),
258
1
        Ok(v) => println!("Result: {v:?}"),
259
    }
260
1
    assert!(
261
1
        result.is_ok(),
262
        "Transaction processing workflow should work"
263
    );
264
1
}