Refactor steps_for_targets to accept Vec<ReportingProductId>

This commit is contained in:
RunasSudo 2025-05-24 01:01:03 +10:00
parent fd761934e0
commit 004f749c33
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
3 changed files with 62 additions and 37 deletions

View File

@ -21,13 +21,10 @@ use libdrcr::db::DbConnection;
use libdrcr::reporting::builders::register_dynamic_builders;
use libdrcr::reporting::calculator::{steps_as_graphviz, steps_for_targets};
use libdrcr::reporting::generate_report;
use libdrcr::reporting::steps::{
register_lookup_fns, AllTransactionsExceptEarningsToEquity,
AllTransactionsIncludingEarningsToEquity, CalculateIncomeTax,
};
use libdrcr::reporting::steps::register_lookup_fns;
use libdrcr::reporting::types::{
DateArgs, DateStartDateEndArgs, ReportingContext, ReportingProductId, ReportingProductKind,
ReportingStep,
VoidArgs,
};
fn main() {
@ -46,13 +43,19 @@ fn main() {
// Print Graphviz
let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax {}),
Box::new(AllTransactionsIncludingEarningsToEquity {
args: DateArgs {
let targets = vec![
ReportingProductId {
name: "CalculateIncomeTax",
kind: ReportingProductKind::Transactions,
args: Box::new(VoidArgs {}),
},
ReportingProductId {
name: "AllTransactionsIncludingEarningsToEquity",
kind: ReportingProductKind::BalancesAt,
args: Box::new(DateArgs {
date: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
}),
},
];
let (sorted_steps, dependencies) = steps_for_targets(targets, &context).unwrap();
@ -61,15 +64,20 @@ fn main() {
// Get income statement
let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax {}),
Box::new(AllTransactionsExceptEarningsToEquity {
product_kinds: &[ReportingProductKind::BalancesBetween],
let targets = vec![
ReportingProductId {
name: "CalculateIncomeTax",
kind: ReportingProductKind::Transactions,
args: Box::new(VoidArgs {}),
},
ReportingProductId {
name: "AllTransactionsExceptEarningsToEquity",
kind: ReportingProductKind::BalancesBetween,
args: Box::new(DateStartDateEndArgs {
date_start: NaiveDate::from_ymd_opt(2024, 7, 1).unwrap(),
date_end: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
}),
}),
},
];
let products = generate_report(targets, &context).unwrap();
@ -89,13 +97,19 @@ fn main() {
// Get balance sheet
let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax {}),
Box::new(AllTransactionsIncludingEarningsToEquity {
args: DateArgs {
let targets = vec![
ReportingProductId {
name: "CalculateIncomeTax",
kind: ReportingProductKind::Transactions,
args: Box::new(VoidArgs {}),
},
ReportingProductId {
name: "AllTransactionsIncludingEarningsToEquity",
kind: ReportingProductKind::BalancesAt,
args: Box::new(DateArgs {
date: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
}),
},
];
let products = generate_report(targets, &context).unwrap();

View File

@ -207,33 +207,41 @@ fn would_be_ready_to_execute(
true
}
/// Recursively resolve the dependencies of the target [ReportingStep]s and return a sorted [Vec] of [ReportingStep]s
/// Recursively resolve the dependencies of the target [ReportingProductId]s and return a sorted [Vec] of [ReportingStep]s
pub fn steps_for_targets(
targets: Vec<Box<dyn ReportingStep>>,
targets: Vec<ReportingProductId>,
context: &ReportingContext,
) -> Result<(Vec<Box<dyn ReportingStep>>, ReportingGraphDependencies), ReportingCalculationError> {
let mut steps: Vec<Box<dyn ReportingStep>> = Vec::new();
let mut dependencies = ReportingGraphDependencies { vec: Vec::new() };
// Initialise targets
for target in targets {
steps.push(target);
let target = steps.last().unwrap();
for dependency in target.requires(&context) {
dependencies.add_dependency(target.id(), dependency);
// Process initial targets
for target in targets.iter() {
if !steps.iter().any(|s| {
s.id().name == target.name
&& s.id().args == target.args
&& s.id().product_kinds.contains(&target.kind)
}) {
// No current step generates the product - try to lookup or build
if let Some(new_step) = build_step_for_product(&target, &steps, &dependencies, context)
{
steps.push(new_step);
let new_step = steps.last().unwrap();
for dependency in new_step.requires(&context) {
dependencies.add_dependency(new_step.id(), dependency);
}
new_step.init_graph(&steps, &mut dependencies, &context);
}
}
target
.as_ref()
.init_graph(&steps, &mut dependencies, &context);
}
// Call after_init_graph on targets
// Call after_init_graph
for step in steps.iter() {
step.as_ref()
.after_init_graph(&steps, &mut dependencies, &context);
}
// Process dependencies
// Recursively process dependencies
loop {
let mut new_steps = Vec::new();

View File

@ -18,7 +18,7 @@
use calculator::{steps_for_targets, ReportingCalculationError};
use executor::{execute_steps, ReportingExecutionError};
use types::{ReportingContext, ReportingProducts, ReportingStep};
use types::{ReportingContext, ReportingProductId, ReportingProducts};
pub mod builders;
pub mod calculator;
@ -44,8 +44,11 @@ impl From<ReportingExecutionError> for ReportingError {
}
}
/// Calculate the steps required to generate the requested [ReportingProductId]s and then execute them
///
/// Helper function to call [steps_for_targets] followed by [execute_steps].
pub fn generate_report(
targets: Vec<Box<dyn ReportingStep>>,
targets: Vec<ReportingProductId>,
context: &ReportingContext,
) -> Result<ReportingProducts, ReportingError> {
// Solve dependencies