Skip to content

Commit

Permalink
Merge pull request #346 from zhang-accounting/345-allow-multiple-lead…
Browse files Browse the repository at this point in the history
…ing-zero-in-amount

345 allow multiple leading zero in amount
  • Loading branch information
Kilerd authored Jun 17, 2024
2 parents 686518b + f1bc117 commit 1f3f940
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 16 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ LABEL org.opencontainers.image.source https://github.com/kilerd/zhang
COPY --chmod=755 zhang /application/

ENV ZHANG_AUTH=""
ENV RUST_LOG="info"
WORKDIR application
VOLUME "/data"
EXPOSE 8000
Expand Down
2 changes: 1 addition & 1 deletion extensions/beancount/src/beancount.pest
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ space = _{ " " | "\t" }
line = _{ NEWLINE }

number = @{
("0" | ASCII_NONZERO_DIGIT ~ (ASCII_DIGIT | "," | "_")*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
(ASCII_DIGIT+ ~ (ASCII_DIGIT | "," | "_")*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
}

number_expr = { expr_atom ~ (space* ~ expr_bin_op ~ space* ~ expr_atom)* }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1970-01-01 open Assets:2 CNY
booking_method: "FIFO"

1970-01-01 balance Assets:2 00.00 CNY

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"uri": "/api/store",
"validations": [
[
"$.data.errors.length()",
0
]
]
}
]
16 changes: 16 additions & 0 deletions integration-tests/allow_multiple_leading_zero_in_amount/main.zhang
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1970-01-01 open Assets:1 CNY
booking_method: "STRICT"

1970-01-01 open Assets:2 CNY
booking_method: "FIFO"


1970-01-01 balance Assets:2 00.00 CNY

1970-01-02 " " ""
Assets:1 -0001.0 CNY
Assets:1 001 CNY

1970-01-02 " " ""
Assets:1 -000.10 CNY
Assets:1 00.1 CNY
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"uri": "/api/store",
"validations": [
[
"$.data.errors.length()",
0
]
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
1970-01-01 open Assets:1 CNY
booking_method: "STRICT"

1970-01-01 open Assets:2 CNY
booking_method: "FIFO"

1970-01-01 balance Assets:2 00.00 CNY

1970-01-02 " " ""
Assets:1 -0001.0 CNY
Assets:1 001 CNY

1970-01-02 " " ""
Assets:1 -000.10 CNY
Assets:1 00.1 CNY
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"uri": "/api/store",
"validations": [
[
"$.data.errors.length()",
0
]
]
}
]
14 changes: 10 additions & 4 deletions zhang-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,13 @@ mod test {
for validation in validations {
pprintln!(" \x1b[0;32mTesting\x1b[0;0m: {}", &validation.uri);

let is_zhang_test = test_temp_folder.join("main.zhang").exists();

let data_source = OpendalDataSource::from_env(
FileSystem::Fs,
&mut ServerOpts {
path: test_temp_folder.clone(),
endpoint: "main.zhang".to_owned(),
endpoint: if is_zhang_test { "main.zhang".to_owned() } else { "main.bean".to_owned() },
addr: "".to_string(),
port: 0,
auth: None,
Expand All @@ -279,9 +281,13 @@ mod test {
)
.await;
let data_source = Arc::new(data_source);
let ledger = Ledger::async_load(test_temp_folder.clone(), "main.zhang".to_owned(), data_source.clone())
.await
.expect("cannot load ledger");
let ledger = Ledger::async_load(
test_temp_folder.clone(),
if is_zhang_test { "main.zhang".to_owned() } else { "main.bean".to_owned() },
data_source.clone(),
)
.await
.expect("cannot load ledger");
let ledger_data = Arc::new(RwLock::new(ledger));
let broadcaster = Broadcaster::create();
let (tx, _) = mpsc::channel(1);
Expand Down
2 changes: 1 addition & 1 deletion zhang-core/src/data_type/text/zhang.pest
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ multiply = { "*" }
divide = { "/" }

number = @{
("0" | ASCII_NONZERO_DIGIT ~ (ASCII_DIGIT | "," | "_")*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
(ASCII_DIGIT+ ~ (ASCII_DIGIT | "," | "_")*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
}
3 changes: 1 addition & 2 deletions zhang-core/src/domains/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ impl Operations {
.find(|meta| meta.key.eq(key.as_ref()))
.cloned())
}
pub fn typed_meta_value<T>(&self, type_: MetaType, type_identifier: impl AsRef<str>, key: impl AsRef<str>) -> ZhangResult<Option<T>>
pub fn typed_meta_value<T>(&self, type_: MetaType, type_identifier: impl AsRef<str>, key: impl AsRef<str>) -> Result<Option<T>, ErrorKind>
where
T: FromStr<Err = ErrorKind>,
{
Expand All @@ -505,7 +505,6 @@ impl Operations {
.find(|meta| meta.key.eq(key.as_ref()))
.map(|it| T::from_str(&it.value))
.transpose()
.map_err(ZhangError::ProcessError)
}

pub fn trx_tags(&mut self, trx_id: &Uuid) -> ZhangResult<Vec<String>> {
Expand Down
5 changes: 3 additions & 2 deletions zhang-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::net::AddrParseError;
use std::path::{Path, PathBuf};

use thiserror::Error;
use zhang_ast::SpanInfo;

#[derive(Debug, Error)]
pub enum ZhangError {
Expand All @@ -24,8 +25,8 @@ pub enum ZhangError {

#[error("Parse Error \nPath: {path}{msg}")]
PestError { path: String, msg: String },
#[error("Process Error: {0}")]
ProcessError(zhang_ast::error::ErrorKind),
#[error("Process Error: {kind} \n file: {:?}[{}:{}] \n content: {}", span.filename,span.start, span.end, span.content)]
ProcessError { span: SpanInfo, kind: zhang_ast::error::ErrorKind },

#[error("cannot found option given key: {0}")]
OptionNotFound(String),
Expand Down
9 changes: 5 additions & 4 deletions zhang-core/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,7 @@ impl Ledger {
ret_ledger.handle_options(&mut options_directives)?;
ret_ledger.async_handle_plugins_pre_process(&mut plugin_directives).await?;
ret_ledger.handle_plugins(&mut plugin_directives)?;

let other_directives = ret_ledger.handle_plugin_execution(other_directives)?;

ret_ledger.handle_other_directives(other_directives)?;

ret_ledger.metas = meta_directives;
Expand Down Expand Up @@ -256,6 +254,8 @@ impl Ledger {
(Some(a_datetime), Some(b_datetime)) => match a_datetime.cmp(&b_datetime) {
Ordering::Equal => match (a.directive_type(), b.directive_type()) {
(DirectiveType::BalancePad | DirectiveType::BalanceCheck, DirectiveType::BalancePad | DirectiveType::BalanceCheck) => Ordering::Equal,
(DirectiveType::Open, DirectiveType::BalancePad | DirectiveType::BalanceCheck) => Ordering::Less,
(DirectiveType::BalancePad | DirectiveType::BalanceCheck, DirectiveType::Open) => Ordering::Greater,
(DirectiveType::BalancePad | DirectiveType::BalanceCheck, _) => Ordering::Less,
(_, DirectiveType::BalancePad | DirectiveType::BalanceCheck) => Ordering::Greater,
(_, _) => Ordering::Equal,
Expand Down Expand Up @@ -323,6 +323,7 @@ impl Ledger {
}

fn handle_plugin_execution(&mut self, other_directives: Vec<Spanned<Directive>>) -> ZhangResult<Vec<Spanned<Directive>>> {
let other_directives = Ledger::sort_directives_datetime(other_directives);
let d = feature_enable!(
self.options.features.plugins,
{
Expand Down Expand Up @@ -543,13 +544,13 @@ mod test {
assert_eq!(
test_parse_zhang(indoc! {r#"
1970-01-01 balance Assets:Hello 2 CNY
1970-01-01 open Assets:Hello
1970-01-01 document Assets:Hello ""
"#})
.into_iter()
.map(|it| it.data)
.collect_vec(),
Ledger::sort_directives_datetime(test_parse_zhang(indoc! {r#"
1970-01-01 open Assets:Hello
1970-01-01 document Assets:Hello ""
1970-01-01 balance Assets:Hello 2 CNY
"#}))
.into_iter()
Expand Down
7 changes: 5 additions & 2 deletions zhang-core/src/process/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ impl DirectiveProcess for Transaction {
trace!("new balance checker starting with {}", &balance_checker);

for (posting_idx, txn_posting) in self.txn_postings().into_iter().enumerate() {
let inferred_amount = txn_posting.infer_trade_amount().map_err(ZhangError::ProcessError)?;
let inferred_amount = txn_posting
.infer_trade_amount()
.map_err(|kind| ZhangError::ProcessError { span: span.clone(), kind })?;

let option = operations.account_target_day_balance(
txn_posting.posting.account.name(),
Expand Down Expand Up @@ -105,7 +107,8 @@ impl DirectiveProcess for Transaction {
let amount = txn_posting.units().unwrap_or(inferred_amount);
let lot_meta = txn_posting.lot_meta();
let booking_method = operations
.typed_meta_value(MetaType::AccountMeta, txn_posting.account_name(), "booking_method")?
.typed_meta_value(MetaType::AccountMeta, txn_posting.account_name(), "booking_method")
.map_err(|kind| ZhangError::ProcessError { span: span.clone(), kind })?
.unwrap_or(ledger.options.default_booking_method);

// handle implicit posting cost
Expand Down

0 comments on commit 1f3f940

Please sign in to comment.