diff --git a/.gitignore b/.gitignore index 6c93088..f4ea39a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target *.json +*.xlsx diff --git a/Cargo.lock b/Cargo.lock index 3e4f298..22d8e94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,11 +2,27 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "antares_get_data" version = "0.1.0" dependencies = [ "reqwest", + "rust_xlsxwriter", "serde", "serde_json", ] @@ -41,6 +57,12 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" @@ -89,6 +111,21 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "displaydoc" version = "0.2.5" @@ -137,6 +174,16 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -557,6 +604,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "leb128fmt" version = "0.1.0" @@ -599,6 +652,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "1.2.0" @@ -738,6 +801,35 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + [[package]] name = "reqwest" version = "0.12.28" @@ -794,6 +886,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust_xlsxwriter" +version = "0.66.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea20da37f12cb312effc50d90a8dab9540648972ec6fbd1e3acb9618eb9fb23" +dependencies = [ + "lazy_static", + "regex", + "zip", +] + [[package]] name = "rustix" version = "1.1.4" @@ -951,6 +1054,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + [[package]] name = "slab" version = "0.4.12" @@ -1645,6 +1754,18 @@ dependencies = [ "syn", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index eb67d05..00a7222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2024" reqwest = { version = "0.12", features = ["blocking"] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } +rust_xlsxwriter = "0.66" diff --git a/src/main.rs b/src/main.rs index edd0010..b44e96a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ use std::error::Error; use std::fs; +use std::time::Duration; +use rust_xlsxwriter::*; mod template; use template::antares::Antares; @@ -11,6 +13,77 @@ fn make_url(base: &str, usercode: &str, password: &str, cikkszam: &str) -> Strin ) } +fn export_to_excel(items: &Antares, filename: &str) -> Result<(), Box> { + let mut workbook = Workbook::new(); + let sheet = workbook.add_worksheet(); + + let header_format = Format::new().set_bold(); + + // Write headers + sheet.write_string_with_format(0, 0, "BESZCIKKSZAM", &header_format)?; + sheet.write_string_with_format(0, 1, "GYCIKKSZAM", &header_format)?; + sheet.write_string_with_format(0, 2, "BESZCIKKNEV", &header_format)?; + sheet.write_string_with_format(0, 3, "GYARTO", &header_format)?; + sheet.write_string_with_format(0, 4, "CIKKAZON", &header_format)?; + sheet.write_string_with_format(0, 5, "KESZLET", &header_format)?; + sheet.write_string_with_format(0, 6, "ME", &header_format)?; + sheet.write_string_with_format(0, 7, "EGYSEGAR", &header_format)?; + + let mut row = 1u32; + for item in items { + // Skip if BESZCIKKSZAM is empty + let cikkszam = match &item.cikkszam { + Some(cs) if !cs.is_empty() => cs.clone(), + _ => continue, + }; + + // BESZCIKKNEV: cikk_megnevezes_rovid or cikk_megnevezes + let megnevezes = item + .cikk_megnevezes_rovid + .clone() + .or_else(|| item.cikk_megnevezes.clone()) + .unwrap_or_default(); + + // Skip if BESZCIKKNEV is empty + if megnevezes.is_empty() { + continue; + } + + // EGYSEGAR: netto_kisker_ar or find in cikk_jellemzok where jellemzo_nev = "Alap ár" + let mut unit_price = item.netto_kisker_ar.unwrap_or(0.0); + if unit_price == 0.0 { + if let Some(ref jellemzok) = item.cikk_jellemzok { + for jellemzo in jellemzok { + if let Some(ref nev) = jellemzo.jellemzo_nev { + if nev == "Alap ár" { + if let Some(ref ertek) = jellemzo.jellemzo_ertek { + unit_price = ertek.parse().unwrap_or(0.0); + break; + } + } + } + } + } + } + + // Write row data + sheet.write_string(row, 0, &cikkszam)?; + sheet.write_string(row, 1, &cikkszam)?; + sheet.write_string(row, 2, &megnevezes)?; + sheet.write_string(row, 3, "EGYEB")?; + sheet.write_string(row, 4, item.vonalkod.as_deref().unwrap_or(""))?; + sheet.write_number(row, 5, item.szabad_keszlet.unwrap_or(0) as f64)?; + sheet.write_string(row, 6, item.mennyisegi_egyseg_kod.as_deref().unwrap_or(""))?; + sheet.write_number(row, 7, unit_price)?; + + row += 1; + } + + workbook.save(filename)?; + println!("Excel file '{}' created with {} rows", filename, row - 1); + Ok(()) +} + fn main() -> Result<(), Box> { // Separate values let base = "https://b2b.antares.hu/I4stechproductionWebInt/IntAntaresWebCikkDataService.svc/webhttps/Get_CikkInfokWeb?SCHEMA=ANTARESINT"; @@ -20,7 +93,10 @@ fn main() -> Result<(), Box> { let url = make_url(base, usercode, password, cikkszam); - let response = reqwest::blocking::get(&url)?.text()?; + let client = reqwest::blocking::Client::builder() + .timeout(Duration::from_secs(300)) + .build()?; + let response = client.get(&url).send()?.text()?; // Try to deserialize into strongly-typed `Antares` list. let items: Antares = match serde_json::from_str::(&response) { @@ -49,6 +125,9 @@ fn main() -> Result<(), Box> { } }; + // Export to Excel + export_to_excel(&items, "antares_export.xlsx")?; + // Example: print first item's Cikkszam if available if let Some(first) = items.get(0) { if let Some(ref cs) = first.cikkszam {