Refactor CalculateIncomeTax

This commit is contained in:
RunasSudo 2025-05-21 18:10:08 +10:00
parent d78d6ed1fe
commit e47ad229eb
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
5 changed files with 54 additions and 85 deletions

View File

@ -24,8 +24,7 @@ use libdrcr::reporting::{
register_lookup_fns, AllTransactionsExceptRetainedEarnings, register_lookup_fns, AllTransactionsExceptRetainedEarnings,
AllTransactionsIncludingRetainedEarnings, CalculateIncomeTax, AllTransactionsIncludingRetainedEarnings, CalculateIncomeTax,
}, },
DateArgs, DateEofyArgs, DateStartDateEndArgs, ReportingContext, ReportingProductKind, DateArgs, DateStartDateEndArgs, ReportingContext, ReportingProductKind, ReportingStep,
ReportingStep,
}; };
fn main() { fn main() {
@ -34,11 +33,7 @@ fn main() {
register_dynamic_builders(&mut context); register_dynamic_builders(&mut context);
let targets: Vec<Box<dyn ReportingStep>> = vec![ let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax { Box::new(CalculateIncomeTax {}),
args: DateEofyArgs {
date_eofy: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
Box::new(AllTransactionsExceptRetainedEarnings { Box::new(AllTransactionsExceptRetainedEarnings {
product_kinds: &[ReportingProductKind::BalancesBetween], product_kinds: &[ReportingProductKind::BalancesBetween],
args: Box::new(DateStartDateEndArgs { args: Box::new(DateStartDateEndArgs {
@ -63,11 +58,7 @@ fn main() {
register_dynamic_builders(&mut context); register_dynamic_builders(&mut context);
let targets: Vec<Box<dyn ReportingStep>> = vec![ let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax { Box::new(CalculateIncomeTax {}),
args: DateEofyArgs {
date_eofy: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
Box::new(AllTransactionsIncludingRetainedEarnings { Box::new(AllTransactionsIncludingRetainedEarnings {
product_kinds: &[ReportingProductKind::BalancesAt], product_kinds: &[ReportingProductKind::BalancesAt],
args: Box::new(DateArgs { args: Box::new(DateArgs {

View File

@ -132,7 +132,7 @@ impl ReportingStep for BalancesAtToBalancesBetween {
} }
} }
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
// BalancesAtToBalancesBetween depends on BalancesAt at both time points // BalancesAtToBalancesBetween depends on BalancesAt at both time points
vec![ vec![
ReportingProductId { ReportingProductId {
@ -191,7 +191,7 @@ impl GenerateBalances {
HasStepOrCanBuild::CanLookup(lookup_fn) => { HasStepOrCanBuild::CanLookup(lookup_fn) => {
// Check for () -> Transactions // Check for () -> Transactions
let step = lookup_fn(args.clone()); let step = lookup_fn(args.clone());
if step.requires().len() == 0 { if step.requires(context).len() == 0 {
return true; return true;
} }
} }
@ -231,7 +231,7 @@ impl ReportingStep for GenerateBalances {
} }
} }
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
// GenerateBalances depends on Transactions // GenerateBalances depends on Transactions
vec![ReportingProductId { vec![ReportingProductId {
name: self.step_name, name: self.step_name,
@ -344,6 +344,7 @@ impl ReportingStep for UpdateBalancesAt {
&self, &self,
steps: &Vec<Box<dyn ReportingStep>>, steps: &Vec<Box<dyn ReportingStep>>,
dependencies: &mut ReportingGraphDependencies, dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) { ) {
// Add a dependency on the Transactions result // Add a dependency on the Transactions result
// Look up that step, so we can extract the appropriate args // Look up that step, so we can extract the appropriate args
@ -458,6 +459,7 @@ impl ReportingStep for UpdateBalancesBetween {
&self, &self,
steps: &Vec<Box<dyn ReportingStep>>, steps: &Vec<Box<dyn ReportingStep>>,
dependencies: &mut ReportingGraphDependencies, dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) { ) {
// Add a dependency on the Transactions result // Add a dependency on the Transactions result
// Look up that step, so we can extract the appropriate args // Look up that step, so we can extract the appropriate args

View File

@ -176,15 +176,15 @@ pub fn solve_for(
for target in targets { for target in targets {
steps.push(target); steps.push(target);
let target = steps.last().unwrap(); let target = steps.last().unwrap();
for dependency in target.requires() { for dependency in target.requires(&context) {
dependencies.add_dependency(target.id(), dependency); dependencies.add_dependency(target.id(), dependency);
} }
target.as_ref().init_graph(&steps, &mut dependencies); target.as_ref().init_graph(&steps, &mut dependencies, &context);
} }
// Call after_init_graph on targets // Call after_init_graph on targets
for step in steps.iter() { for step in steps.iter() {
step.as_ref().after_init_graph(&steps, &mut dependencies); step.as_ref().after_init_graph(&steps, &mut dependencies, &context);
} }
// Process dependencies // Process dependencies
@ -265,15 +265,15 @@ pub fn solve_for(
new_step_indexes.push(steps.len()); new_step_indexes.push(steps.len());
steps.push(new_step); steps.push(new_step);
let new_step = steps.last().unwrap(); let new_step = steps.last().unwrap();
for dependency in new_step.requires() { for dependency in new_step.requires(&context) {
dependencies.add_dependency(new_step.id(), dependency); dependencies.add_dependency(new_step.id(), dependency);
} }
new_step.as_ref().init_graph(&steps, &mut dependencies); new_step.as_ref().init_graph(&steps, &mut dependencies, &context);
} }
// Call after_init_graph on all steps // Call after_init_graph on all steps
for step in steps.iter() { for step in steps.iter() {
step.as_ref().after_init_graph(&steps, &mut dependencies); step.as_ref().after_init_graph(&steps, &mut dependencies, &context);
} }
} }

View File

@ -30,7 +30,7 @@ pub mod calculator;
pub mod steps; pub mod steps;
pub struct ReportingContext { pub struct ReportingContext {
_eofy_date: NaiveDate, eofy_date: NaiveDate,
step_lookup_fn: HashMap< step_lookup_fn: HashMap<
(&'static str, &'static [ReportingProductKind]), (&'static str, &'static [ReportingProductKind]),
(ReportingStepTakesArgsFn, ReportingStepFromArgsFn), (ReportingStepTakesArgsFn, ReportingStepFromArgsFn),
@ -41,7 +41,7 @@ pub struct ReportingContext {
impl ReportingContext { impl ReportingContext {
pub fn new(eofy_date: NaiveDate) -> Self { pub fn new(eofy_date: NaiveDate) -> Self {
Self { Self {
_eofy_date: eofy_date, eofy_date: eofy_date,
step_lookup_fn: HashMap::new(), step_lookup_fn: HashMap::new(),
step_dynamic_builders: Vec::new(), step_dynamic_builders: Vec::new(),
} }
@ -126,7 +126,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
fn id(&self) -> ReportingStepId; fn id(&self) -> ReportingStepId;
// Methods // Methods
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
vec![] vec![]
} }
@ -134,6 +134,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
&self, &self,
_steps: &Vec<Box<dyn ReportingStep>>, _steps: &Vec<Box<dyn ReportingStep>>,
_dependencies: &mut ReportingGraphDependencies, _dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) { ) {
} }
@ -141,6 +142,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
&self, &self,
_steps: &Vec<Box<dyn ReportingStep>>, _steps: &Vec<Box<dyn ReportingStep>>,
_dependencies: &mut ReportingGraphDependencies, _dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) { ) {
} }
@ -160,6 +162,17 @@ dyn_eq::eq_trait_object!(ReportingStepArgs);
pub type ReportingStepTakesArgsFn = fn(args: &Box<dyn ReportingStepArgs>) -> bool; pub type ReportingStepTakesArgsFn = fn(args: &Box<dyn ReportingStepArgs>) -> bool;
pub type ReportingStepFromArgsFn = fn(args: Box<dyn ReportingStepArgs>) -> Box<dyn ReportingStep>; pub type ReportingStepFromArgsFn = fn(args: Box<dyn ReportingStepArgs>) -> Box<dyn ReportingStep>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VoidArgs {}
impl ReportingStepArgs for VoidArgs {}
impl Display for VoidArgs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(""))
}
}
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct DateArgs { pub struct DateArgs {
pub date: NaiveDate, pub date: NaiveDate,
@ -173,19 +186,6 @@ impl Display for DateArgs {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DateEofyArgs {
pub date_eofy: NaiveDate,
}
impl ReportingStepArgs for DateEofyArgs {}
impl Display for DateEofyArgs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.date_eofy))
}
}
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct DateStartDateEndArgs { pub struct DateStartDateEndArgs {
pub date_start: NaiveDate, pub date_start: NaiveDate,

View File

@ -21,9 +21,9 @@ use std::fmt::Display;
use crate::util::sofy_from_eofy; use crate::util::sofy_from_eofy;
use super::{ use super::{
calculator::ReportingGraphDependencies, DateArgs, DateEofyArgs, DateStartDateEndArgs, calculator::ReportingGraphDependencies, DateArgs, DateStartDateEndArgs, ReportingContext,
ReportingContext, ReportingProductId, ReportingProductKind, ReportingStep, ReportingStepArgs, ReportingProductId, ReportingProductKind, ReportingStep, ReportingStepArgs, ReportingStepId,
ReportingStepId, VoidArgs,
}; };
pub fn register_lookup_fns(context: &mut ReportingContext) { pub fn register_lookup_fns(context: &mut ReportingContext) {
@ -176,7 +176,7 @@ impl ReportingStep for AllTransactionsIncludingRetainedEarnings {
} }
} }
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
vec![ReportingProductId { vec![ReportingProductId {
name: "AllTransactionsExceptRetainedEarnings", name: "AllTransactionsExceptRetainedEarnings",
kind: self.product_kinds[0], kind: self.product_kinds[0],
@ -186,19 +186,15 @@ impl ReportingStep for AllTransactionsIncludingRetainedEarnings {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct CalculateIncomeTax { pub struct CalculateIncomeTax {}
pub args: DateEofyArgs,
}
impl CalculateIncomeTax { impl CalculateIncomeTax {
fn takes_args(args: &Box<dyn ReportingStepArgs>) -> bool { fn takes_args(_args: &Box<dyn ReportingStepArgs>) -> bool {
args.is::<DateEofyArgs>() true
} }
fn from_args(args: Box<dyn ReportingStepArgs>) -> Box<dyn ReportingStep> { fn from_args(_args: Box<dyn ReportingStepArgs>) -> Box<dyn ReportingStep> {
Box::new(CalculateIncomeTax { Box::new(CalculateIncomeTax {})
args: *args.downcast().unwrap(),
})
} }
} }
@ -213,18 +209,18 @@ impl ReportingStep for CalculateIncomeTax {
ReportingStepId { ReportingStepId {
name: "CalculateIncomeTax", name: "CalculateIncomeTax",
product_kinds: &[ReportingProductKind::Transactions], product_kinds: &[ReportingProductKind::Transactions],
args: Box::new(self.args.clone()), args: Box::new(VoidArgs {}),
} }
} }
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, context: &ReportingContext) -> Vec<ReportingProductId> {
// CalculateIncomeTax depends on CombineOrdinaryTransactions // CalculateIncomeTax depends on CombineOrdinaryTransactions
vec![ReportingProductId { vec![ReportingProductId {
name: "CombineOrdinaryTransactions", name: "CombineOrdinaryTransactions",
kind: ReportingProductKind::BalancesBetween, kind: ReportingProductKind::BalancesBetween,
args: Box::new(DateStartDateEndArgs { args: Box::new(DateStartDateEndArgs {
date_start: sofy_from_eofy(self.args.date_eofy), date_start: sofy_from_eofy(context.eofy_date),
date_end: self.args.date_eofy.clone(), date_end: context.eofy_date.clone(),
}), }),
}] }]
} }
@ -233,13 +229,11 @@ impl ReportingStep for CalculateIncomeTax {
&self, &self,
steps: &Vec<Box<dyn ReportingStep>>, steps: &Vec<Box<dyn ReportingStep>>,
dependencies: &mut ReportingGraphDependencies, dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) { ) {
for other in steps { for other in steps {
if let Some(other) = other.downcast_ref::<AllTransactionsExceptRetainedEarnings>() { if let Some(other) = other.downcast_ref::<AllTransactionsExceptRetainedEarnings>() {
// AllTransactionsExceptRetainedEarnings (in applicable periods) depends on CalculateIncomeTax // AllTransactionsExceptRetainedEarnings depends on CalculateIncomeTax
if other.args.is::<DateArgs>() {
let other_args = other.args.downcast_ref::<DateArgs>().unwrap();
if other_args.date >= self.args.date_eofy {
dependencies.add_dependency( dependencies.add_dependency(
other.id(), other.id(),
ReportingProductId { ReportingProductId {
@ -249,24 +243,6 @@ impl ReportingStep for CalculateIncomeTax {
}, },
); );
} }
} else if other.args.is::<DateStartDateEndArgs>() {
let other_args = other.args.downcast_ref::<DateStartDateEndArgs>().unwrap();
if other_args.date_start <= self.args.date_eofy
&& other_args.date_end >= self.args.date_eofy
{
dependencies.add_dependency(
other.id(),
ReportingProductId {
name: self.id().name,
kind: other.product_kinds[0],
args: other.id().args,
},
);
}
} else {
unreachable!();
}
}
} }
} }
} }
@ -303,7 +279,7 @@ impl ReportingStep for CombineOrdinaryTransactions {
} }
} }
fn requires(&self) -> Vec<ReportingProductId> { fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
vec![ vec![
// CombineOrdinaryTransactions depends on DBBalances // CombineOrdinaryTransactions depends on DBBalances
ReportingProductId { ReportingProductId {