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,
AllTransactionsIncludingRetainedEarnings, CalculateIncomeTax,
},
DateArgs, DateEofyArgs, DateStartDateEndArgs, ReportingContext, ReportingProductKind,
ReportingStep,
DateArgs, DateStartDateEndArgs, ReportingContext, ReportingProductKind, ReportingStep,
};
fn main() {
@ -34,11 +33,7 @@ fn main() {
register_dynamic_builders(&mut context);
let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax {
args: DateEofyArgs {
date_eofy: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
Box::new(CalculateIncomeTax {}),
Box::new(AllTransactionsExceptRetainedEarnings {
product_kinds: &[ReportingProductKind::BalancesBetween],
args: Box::new(DateStartDateEndArgs {
@ -63,11 +58,7 @@ fn main() {
register_dynamic_builders(&mut context);
let targets: Vec<Box<dyn ReportingStep>> = vec![
Box::new(CalculateIncomeTax {
args: DateEofyArgs {
date_eofy: NaiveDate::from_ymd_opt(2025, 6, 30).unwrap(),
},
}),
Box::new(CalculateIncomeTax {}),
Box::new(AllTransactionsIncludingRetainedEarnings {
product_kinds: &[ReportingProductKind::BalancesAt],
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
vec![
ReportingProductId {
@ -191,7 +191,7 @@ impl GenerateBalances {
HasStepOrCanBuild::CanLookup(lookup_fn) => {
// Check for () -> Transactions
let step = lookup_fn(args.clone());
if step.requires().len() == 0 {
if step.requires(context).len() == 0 {
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
vec![ReportingProductId {
name: self.step_name,
@ -344,6 +344,7 @@ impl ReportingStep for UpdateBalancesAt {
&self,
steps: &Vec<Box<dyn ReportingStep>>,
dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) {
// Add a dependency on the Transactions result
// Look up that step, so we can extract the appropriate args
@ -458,6 +459,7 @@ impl ReportingStep for UpdateBalancesBetween {
&self,
steps: &Vec<Box<dyn ReportingStep>>,
dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) {
// Add a dependency on the Transactions result
// 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 {
steps.push(target);
let target = steps.last().unwrap();
for dependency in target.requires() {
for dependency in target.requires(&context) {
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
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
@ -265,15 +265,15 @@ pub fn solve_for(
new_step_indexes.push(steps.len());
steps.push(new_step);
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);
}
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
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 struct ReportingContext {
_eofy_date: NaiveDate,
eofy_date: NaiveDate,
step_lookup_fn: HashMap<
(&'static str, &'static [ReportingProductKind]),
(ReportingStepTakesArgsFn, ReportingStepFromArgsFn),
@ -41,7 +41,7 @@ pub struct ReportingContext {
impl ReportingContext {
pub fn new(eofy_date: NaiveDate) -> Self {
Self {
_eofy_date: eofy_date,
eofy_date: eofy_date,
step_lookup_fn: HashMap::new(),
step_dynamic_builders: Vec::new(),
}
@ -126,7 +126,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
fn id(&self) -> ReportingStepId;
// Methods
fn requires(&self) -> Vec<ReportingProductId> {
fn requires(&self, _context: &ReportingContext) -> Vec<ReportingProductId> {
vec![]
}
@ -134,6 +134,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
&self,
_steps: &Vec<Box<dyn ReportingStep>>,
_dependencies: &mut ReportingGraphDependencies,
_context: &ReportingContext,
) {
}
@ -141,6 +142,7 @@ pub trait ReportingStep: Debug + Display + Downcast {
&self,
_steps: &Vec<Box<dyn ReportingStep>>,
_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 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)]
pub struct DateArgs {
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)]
pub struct DateStartDateEndArgs {
pub date_start: NaiveDate,

View File

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