#![cfg_attr(not(test), deny(clippy::unwrap_used))]
use std::path::{Path, PathBuf};
pub mod compressed;
pub mod control_export;
pub mod csv_sink;
pub mod esg_export;
pub mod fast_csv;
pub mod formats;
pub mod json_sink;
pub mod parquet_sink;
pub mod project_accounting_export;
pub mod streaming;
pub mod tax_export;
pub mod treasury_export;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OutputRootConfig {
pub root_dir: PathBuf,
pub per_entity_subtree: bool,
pub entity_code: Option<String>,
}
impl OutputRootConfig {
pub fn flat(root_dir: impl Into<PathBuf>) -> Self {
Self {
root_dir: root_dir.into(),
per_entity_subtree: false,
entity_code: None,
}
}
pub fn per_entity(root_dir: impl Into<PathBuf>, entity_code: impl Into<String>) -> Self {
Self {
root_dir: root_dir.into(),
per_entity_subtree: true,
entity_code: Some(entity_code.into()),
}
}
pub fn effective_dir(&self) -> PathBuf {
match (self.per_entity_subtree, &self.entity_code) {
(true, Some(code)) => self.root_dir.join("entities").join(code),
(false, _) | (true, None) => self.root_dir.clone(),
}
}
pub fn root_path(&self) -> &Path {
&self.root_dir
}
}
impl Default for OutputRootConfig {
fn default() -> Self {
Self::flat(PathBuf::from("."))
}
}
pub use compressed::{CompressedWriter, CompressionConfig};
pub use control_export::*;
pub use csv_sink::*;
pub use esg_export::*;
pub use formats::{
saft_naive_date, write_anla, write_bsad, write_bsak, write_bsas, write_bsid, write_bsik,
write_bsis, write_cepc, write_csks, write_ekko, write_ekpo, write_fec_csv,
write_gobd_accounts_csv, write_gobd_index_xml, write_gobd_journal_csv, write_kna1, write_knb1,
write_lfa1, write_lfb1, write_likp, write_lips, write_mara, write_mard, write_mkpf, write_mseg,
write_saft, write_ska1, write_skb1, write_vbak, write_vbap, NetSuiteExporter,
NetSuiteJournalEntry, NetSuiteJournalLine, OracleExporter, OracleJeHeader, OracleJeLine,
SaftConfig, SaftData, SaftJurisdiction, SapAsset, SapAssetExportable, SapClearedItemRow,
SapCostCenter, SapCostCenterExportable, SapCustomer, SapCustomerCompanyCode,
SapCustomerCompanyCodeExportable, SapCustomerExportable, SapDeliveryExportable,
SapDeliveryHeader, SapDeliveryItem, SapDialect, SapExportConfig, SapExporter,
SapGlAccountCompanyCode, SapGlAccountExportable, SapGlAccountGeneral, SapMatDocExportable,
SapMatDocHeader, SapMatDocItem, SapMaterial, SapMaterialExportable, SapMaterialStorage,
SapMaterialStorageExportable, SapOpenItemRow, SapPoExportable, SapPoHeader, SapPoItem,
SapProfitCenter, SapProfitCenterExportable, SapSoExportable, SapSoHeader, SapSoItem,
SapTableType, SapVendor, SapVendorCompanyCode, SapVendorCompanyCodeExportable,
SapVendorExportable, XbrlExporter,
};
pub use json_sink::*;
pub use parquet_sink::*;
pub use project_accounting_export::*;
pub use streaming::{
CsvStreamingSink, JsonStreamingSink, NdjsonStreamingSink, ParquetStreamingSink,
};
pub use tax_export::*;
pub use treasury_export::*;
#[cfg(test)]
mod test_helpers;
#[cfg(test)]
mod output_root_config_tests {
use super::*;
use std::path::Path;
#[test]
fn flat_mode_returns_root_dir() {
let cfg = OutputRootConfig::flat("/tmp/out");
assert_eq!(cfg.effective_dir(), Path::new("/tmp/out"));
assert!(!cfg.per_entity_subtree);
assert!(cfg.entity_code.is_none());
}
#[test]
fn per_entity_mode_routes_under_entities_code() {
let cfg = OutputRootConfig::per_entity("/tmp/out", "ACME_SA");
assert_eq!(cfg.effective_dir(), Path::new("/tmp/out/entities/ACME_SA"));
assert!(cfg.per_entity_subtree);
assert_eq!(cfg.entity_code.as_deref(), Some("ACME_SA"));
}
#[test]
fn per_entity_true_without_code_falls_back_to_root() {
let cfg = OutputRootConfig {
root_dir: "/tmp/out".into(),
per_entity_subtree: true,
entity_code: None,
};
assert_eq!(cfg.effective_dir(), Path::new("/tmp/out"));
}
#[test]
fn default_is_flat_at_cwd() {
let cfg = OutputRootConfig::default();
assert_eq!(cfg.effective_dir(), Path::new("."));
assert!(!cfg.per_entity_subtree);
assert!(cfg.entity_code.is_none());
}
#[test]
fn root_path_always_returns_root_regardless_of_mode() {
let flat = OutputRootConfig::flat("/tmp/out");
assert_eq!(flat.root_path(), Path::new("/tmp/out"));
let per_entity = OutputRootConfig::per_entity("/tmp/out", "ENT_A");
assert_eq!(per_entity.root_path(), Path::new("/tmp/out"));
}
}