1use crate::cli::setup_domain;
2use crate::client::accounting_info::AccountingInfoClient;
3use crate::client::sales::SalesClient;
4use crate::config::Config;
5use crate::error::YukiError;
6use crate::output::{
7 ListOptions, OutputFormat, apply_pagination, format_json, format_table, is_tty, select_fields,
8};
9
10pub async fn list(
11 config: &Config,
12 admin: Option<&str>,
13 _period: Option<&str>,
14 invoice_type: Option<&str>,
15 format: Option<&str>,
16 opts: ListOptions<'_>,
17) -> Result<(), YukiError> {
18 let fmt = OutputFormat::from_flag(format, is_tty());
19
20 match invoice_type {
21 Some("purchase") | Some("creditor") => {
22 let (client, entry) = setup_domain(config, admin).await?;
23 let items = client.outstanding_creditor_items(&entry.admin_id).await?;
24
25 let mut headers = vec![
26 "Contact".into(),
27 "Description".into(),
28 "Date".into(),
29 "Amount".into(),
30 "Open".into(),
31 ];
32 let mut rows: Vec<Vec<String>> = items
33 .iter()
34 .map(|i| {
35 vec![
36 i.contact_name.clone(),
37 i.description.clone(),
38 i.date.clone(),
39 i.amount.clone(),
40 i.open_amount.clone(),
41 ]
42 })
43 .collect();
44 apply_pagination(&mut rows, &opts);
45 select_fields(&mut headers, &mut rows, &opts)?;
46
47 match fmt {
48 OutputFormat::Table => println!("{}", format_table(&headers, &rows)),
49 OutputFormat::Json => println!("{}", format_json(&headers, &rows)),
50 }
51 }
52
53 _ => {
55 let mut client = SalesClient::new();
56 client.authenticate(&config.api_key).await?;
57 let items = client.get_sales_items().await?;
58
59 let mut headers = vec!["ID".into(), "Description".into()];
60 let mut rows: Vec<Vec<String>> = items
61 .iter()
62 .map(|i| vec![i.id.clone(), i.description.clone()])
63 .collect();
64 apply_pagination(&mut rows, &opts);
65 select_fields(&mut headers, &mut rows, &opts)?;
66
67 match fmt {
68 OutputFormat::Table => println!("{}", format_table(&headers, &rows)),
69 OutputFormat::Json => println!("{}", format_json(&headers, &rows)),
70 }
71 }
72 }
73
74 Ok(())
75}
76
77pub async fn document(
78 config: &Config,
79 admin: Option<&str>,
80 id: &str,
81 format: Option<&str>,
82) -> Result<(), YukiError> {
83 let entry = config.resolve_admin(admin)?;
84 let mut client = AccountingInfoClient::new();
85 client.authenticate(&config.api_key).await?;
86 let xml = client.get_transaction_document(&entry.admin_id, id).await?;
87
88 let result = crate::client::soap_client::SoapClient::parse_single_result(
89 &xml,
90 "GetTransactionDocumentResult",
91 )
92 .unwrap_or(xml);
93
94 let headers = vec!["Transaction".into(), "Document".into()];
95 let rows = vec![vec![id.to_string(), result]];
96
97 let fmt = OutputFormat::from_flag(format, is_tty());
98 match fmt {
99 OutputFormat::Table => println!("{}", format_table(&headers, &rows)),
100 OutputFormat::Json => println!("{}", format_json(&headers, &rows)),
101 }
102 Ok(())
103}
104
105pub async fn show(
106 config: &Config,
107 _admin: Option<&str>,
108 id: &str,
109 format: Option<&str>,
110) -> Result<(), YukiError> {
111 let mut client = AccountingInfoClient::new();
112 client.authenticate(&config.api_key).await?;
113 let details = client.get_transaction_details(id).await?;
114
115 let headers = vec![
116 "ID".into(),
117 "Date".into(),
118 "Amount".into(),
119 "Currency".into(),
120 "GL Account".into(),
121 "Description".into(),
122 ];
123 let rows: Vec<Vec<String>> = details
124 .iter()
125 .map(|d| {
126 vec![
127 d.id.clone(),
128 d.date.clone(),
129 d.amount.clone(),
130 d.currency.clone(),
131 d.gl_account_code.clone(),
132 d.description.clone(),
133 ]
134 })
135 .collect();
136
137 let fmt = OutputFormat::from_flag(format, is_tty());
138 match fmt {
139 OutputFormat::Table => println!("{}", format_table(&headers, &rows)),
140 OutputFormat::Json => println!("{}", format_json(&headers, &rows)),
141 }
142 Ok(())
143}