Basic framework for executing reports
This commit is contained in:
parent
9e34360abf
commit
db89814498
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -82,6 +82,12 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c2d035d21af5cde1a6f5c7b444a5bf963520a9f142e5d06931178433d7d5388"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-hash"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15401da73a9ed8c80e3b2d4dc05fe10e7b72d7243b9f614e516a44fa99986e88"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
@ -130,6 +136,7 @@ dependencies = [
|
||||
"downcast-rs",
|
||||
"dyn-clone",
|
||||
"dyn-eq",
|
||||
"dyn-hash",
|
||||
"solvent",
|
||||
]
|
||||
|
||||
|
@ -8,4 +8,5 @@ chrono = "0.4.41"
|
||||
downcast-rs = "2.0.1"
|
||||
dyn-clone = "1.0.19"
|
||||
dyn-eq = "0.1.3"
|
||||
dyn-hash = "0.2.2"
|
||||
solvent = "0.8.3"
|
||||
|
@ -1,3 +1,5 @@
|
||||
pub mod reporting;
|
||||
pub mod transaction;
|
||||
pub mod util;
|
||||
|
||||
pub type QuantityInt = u64;
|
||||
|
40
src/main.rs
40
src/main.rs
@ -18,13 +18,12 @@
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use libdrcr::reporting::builders::register_dynamic_builders;
|
||||
use libdrcr::reporting::calculator::steps_for_targets;
|
||||
use libdrcr::reporting::generate_report;
|
||||
use libdrcr::reporting::steps::{
|
||||
register_lookup_fns, AllTransactionsExceptRetainedEarnings,
|
||||
AllTransactionsIncludingRetainedEarnings, CalculateIncomeTax,
|
||||
register_lookup_fns, AllTransactionsExceptRetainedEarnings, CalculateIncomeTax,
|
||||
};
|
||||
use libdrcr::reporting::types::{
|
||||
DateArgs, DateStartDateEndArgs, ReportingContext, ReportingProductKind, ReportingStep,
|
||||
DateStartDateEndArgs, ReportingContext, ReportingProductKind, ReportingStep,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@ -43,36 +42,7 @@ fn main() {
|
||||
}),
|
||||
];
|
||||
|
||||
println!("For income statement:");
|
||||
match steps_for_targets(targets, context) {
|
||||
Ok(steps) => {
|
||||
for step in steps {
|
||||
println!("- {}", step);
|
||||
}
|
||||
}
|
||||
Err(err) => panic!("Error: {:?}", err),
|
||||
}
|
||||
let products = generate_report(targets, &context);
|
||||
|
||||
let mut context = ReportingContext::new(NaiveDate::from_ymd_opt(2025, 6, 30).unwrap());
|
||||
register_lookup_fns(&mut context);
|
||||
register_dynamic_builders(&mut context);
|
||||
|
||||
let targets: Vec<Box<dyn ReportingStep>> = vec![
|
||||
Box::new(CalculateIncomeTax {}),
|
||||
Box::new(AllTransactionsIncludingRetainedEarnings {
|
||||
args: DateArgs {
|
||||
date: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
println!("For balance sheet:");
|
||||
match steps_for_targets(targets, context) {
|
||||
Ok(steps) => {
|
||||
for step in steps {
|
||||
println!("- {}", step);
|
||||
}
|
||||
}
|
||||
Err(err) => panic!("Error: {:?}", err),
|
||||
}
|
||||
println!("{:?}", products);
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ fn would_be_ready_to_execute(
|
||||
/// Recursively resolve the dependencies of the target [ReportingStep]s and return a sorted [Vec] of [ReportingStep]s
|
||||
pub fn steps_for_targets(
|
||||
targets: Vec<Box<dyn ReportingStep>>,
|
||||
context: ReportingContext,
|
||||
context: &ReportingContext,
|
||||
) -> Result<Vec<Box<dyn ReportingStep>>, ReportingCalculationError> {
|
||||
let mut steps: Vec<Box<dyn ReportingStep>> = Vec::new();
|
||||
let mut dependencies = ReportingGraphDependencies { vec: Vec::new() };
|
||||
|
37
src/reporting/executor.rs
Normal file
37
src/reporting/executor.rs
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
DrCr: Web-based double-entry bookkeeping framework
|
||||
Copyright (C) 2022-2025 Lee Yingtong Li (RunasSudo)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use super::types::{ReportingContext, ReportingProducts, ReportingStep};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReportingExecutionError {
|
||||
message: String,
|
||||
}
|
||||
|
||||
pub fn execute_steps(
|
||||
steps: Vec<Box<dyn ReportingStep>>,
|
||||
context: &ReportingContext,
|
||||
) -> Result<ReportingProducts, ReportingExecutionError> {
|
||||
let mut products = ReportingProducts::new();
|
||||
|
||||
for step in steps {
|
||||
step.execute(context, &mut products)?;
|
||||
}
|
||||
|
||||
Ok(products)
|
||||
}
|
@ -16,7 +16,43 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use calculator::{steps_for_targets, ReportingCalculationError};
|
||||
use executor::{execute_steps, ReportingExecutionError};
|
||||
use types::{ReportingContext, ReportingProducts, ReportingStep};
|
||||
|
||||
pub mod builders;
|
||||
pub mod calculator;
|
||||
pub mod executor;
|
||||
pub mod steps;
|
||||
pub mod types;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ReportingError {
|
||||
ReportingCalculationError(ReportingCalculationError),
|
||||
ReportingExecutionError(ReportingExecutionError),
|
||||
}
|
||||
|
||||
impl From<ReportingCalculationError> for ReportingError {
|
||||
fn from(err: ReportingCalculationError) -> Self {
|
||||
ReportingError::ReportingCalculationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReportingExecutionError> for ReportingError {
|
||||
fn from(err: ReportingExecutionError) -> Self {
|
||||
ReportingError::ReportingExecutionError(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_report(
|
||||
targets: Vec<Box<dyn ReportingStep>>,
|
||||
context: &ReportingContext,
|
||||
) -> Result<ReportingProducts, ReportingError> {
|
||||
// Solve dependencies
|
||||
let sorted_steps = steps_for_targets(targets, context)?;
|
||||
|
||||
// Execute steps
|
||||
let products = execute_steps(sorted_steps, context)?;
|
||||
|
||||
Ok(products)
|
||||
}
|
||||
|
@ -16,15 +16,22 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
|
||||
use chrono::Datelike;
|
||||
|
||||
use crate::reporting::types::{BalancesAt, DateStartDateEndArgs, ReportingProduct, ReportingProductId};
|
||||
use crate::reporting::types::{
|
||||
BalancesAt, DateStartDateEndArgs, ReportingProduct, ReportingProductId,
|
||||
};
|
||||
use crate::util::sofy_from_eofy;
|
||||
|
||||
use super:: calculator::ReportingGraphDependencies;
|
||||
use super::types::{DateArgs, ReportingContext, ReportingProductKind, ReportingProducts, ReportingStep, ReportingStepArgs, ReportingStepId, VoidArgs};
|
||||
use super::calculator::ReportingGraphDependencies;
|
||||
use super::executor::ReportingExecutionError;
|
||||
use super::types::{
|
||||
DateArgs, ReportingContext, ReportingProductKind, ReportingProducts, ReportingStep,
|
||||
ReportingStepArgs, ReportingStepId, VoidArgs,
|
||||
};
|
||||
|
||||
pub fn register_lookup_fns(context: &mut ReportingContext) {
|
||||
context.register_lookup_fn(
|
||||
@ -322,6 +329,29 @@ impl ReportingStep for DBBalances {
|
||||
args: Box::new(self.args.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(
|
||||
&self,
|
||||
_context: &ReportingContext,
|
||||
products: &mut ReportingProducts,
|
||||
) -> Result<(), ReportingExecutionError> {
|
||||
eprintln!("Stub: DBBalances.execute");
|
||||
|
||||
let balances = BalancesAt {
|
||||
balances: HashMap::new(),
|
||||
};
|
||||
|
||||
products.insert(
|
||||
ReportingProductId {
|
||||
name: self.id().name,
|
||||
kind: ReportingProductKind::BalancesAt,
|
||||
args: Box::new(self.args.clone()),
|
||||
},
|
||||
ReportingProduct::BalancesAt(balances),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -28,6 +28,7 @@ use dyn_hash::DynHash;
|
||||
use crate::QuantityInt;
|
||||
|
||||
use super::calculator::ReportingGraphDependencies;
|
||||
use super::executor::ReportingExecutionError;
|
||||
|
||||
// -----------------
|
||||
// REPORTING CONTEXT
|
||||
@ -143,6 +144,7 @@ pub enum ReportingProductKind {
|
||||
}
|
||||
|
||||
/// Represents the result of a [ReportingStep]
|
||||
#[derive(Debug)]
|
||||
pub enum ReportingProduct {
|
||||
Transactions(Transactions),
|
||||
BalancesAt(BalancesAt),
|
||||
@ -151,18 +153,21 @@ pub enum ReportingProduct {
|
||||
}
|
||||
|
||||
/// Records a list of transactions generated by a [ReportingStep]
|
||||
#[derive(Debug)]
|
||||
pub struct Transactions {}
|
||||
|
||||
/// Records cumulative account balances at a particular point in time
|
||||
#[derive(Debug)]
|
||||
pub struct BalancesAt {
|
||||
pub balances: HashMap<String, QuantityInt>,
|
||||
}
|
||||
|
||||
/// Records the total value of transactions in each account between two points in time
|
||||
#[derive(Debug)]
|
||||
pub struct BalancesBetween {}
|
||||
|
||||
/// Represents a custom [ReportingProduct] generated by a [ReportingStep]
|
||||
pub trait GenericReportingProduct {}
|
||||
pub trait GenericReportingProduct: Debug {}
|
||||
|
||||
/// Convenience type mapping [ReportingProductId] to [ReportingProduct]
|
||||
pub type ReportingProducts = HashMap<ReportingProductId, ReportingProduct>;
|
||||
@ -222,8 +227,12 @@ pub trait ReportingStep: Debug + Display + Downcast {
|
||||
|
||||
/// Called to generate the [ReportingProduct] for this [ReportingStep]
|
||||
#[allow(unused_variables)]
|
||||
fn execute(&self, context: &ReportingContext, products: &mut ReportingProducts) {
|
||||
todo!();
|
||||
fn execute(
|
||||
&self,
|
||||
context: &ReportingContext,
|
||||
products: &mut ReportingProducts,
|
||||
) -> Result<(), ReportingExecutionError> {
|
||||
todo!("{}", self);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user