Skip to main content

ALToolbox.al_income

DAObject​

DADict​

DAList​

DAOrderedDict​

DAEmpty​

Individual​

comma_list​

get_locale​

word​

log​

object_name_convert​

value​

Decimal​

re​

datetime​

functions​

json​

Any​

Dict​

Callable​

List​

Optional​

Set​

Union​

Tuple​

Mapping​

__all__​

_currency_float_to_decimal​

def _currency_float_to_decimal(value: Union[str, float]) -> Decimal

Convert a currency float value to precise Decimal representation.

Given a float that was set by a docassemble currency datatype (rounded to the nearest fractional_digit decimal places), returns the exact decimal value without floating point representation errors.

Arguments​

  • value Union[str, float] - The currency value to convert, either as a float or string representation.

Returns​

  • Decimal - The precise decimal representation of the currency value.

times_per_year​

def times_per_year(times_per_year_list: List[Tuple[int, str]],
times_per_year: float) -> str

Get the lower-case textual description that matches a time period contained in a "times per year" list.

The goal of this function is to allow you to reflect the user's selection back to them, either on screen or in a document.

In al_income.yml there is a default times_per_year_list, but the list that you use must be passed as a parameter as it's common to want to customize this for a given financial statement.

For example: if the times_per_year is 12, it will return "monthly" from the default times_per_year_list.

If the times per year does not exist in the given list, it will return a literal string like "five times per year".

Fractional or floating point-based times_per_year are permissible in the times_per_year_list, although they are not commonly used. E.g., .5 would represent "every two years". Items not contained in the list (to provide a specific lookup name) will have a string representation that is rounded to the nearest whole integer.

Arguments​

  • times_per_year_list List[Tuple[int, str]] - List of tuples containing (frequency, description) pairs to match against.
  • times_per_year float - The numeric frequency to look up in the list.

Returns​

The lowercase textual description of the frequency, or a generated description if not found in the list.

Example​

With a gathered users[0].incomes list containing monthly non-hourly entries for wages (value=1000, source="wages") and benefits (value=250, source="benefits"), both with times_per_year=12, and US English currency formatting:

Input (Mako)

${ times_per_year([(12, "Monthly"), (1, "Annually")], users[0].incomes[0].times_per_year) }

Input (Jinja2)

{{ times_per_year([(12, "Monthly"), (1, "Annually")], users[0].incomes[0].times_per_year) }}

Output

monthly

recent_years​

def recent_years(past: int = 25,
order: str = "descending",
future: int = 1) -> List[int]

Returns a list of the most recent past years, continuing into the future.

Defaults to most recent 25 years+1. Useful to populate a combobox of years where the most recent ones are most likely. E.g. automobile years or birthdate.

Arguments​

  • past int, optional - The number of past years to list, including the current year. Defaults to 25.
  • order str, optional - 'descending' or 'ascending'. Defaults to 'descending'.
  • future int, optional - Number of future years to include. Defaults to 1.

Returns​

  • List[int] - List of years in the specified order.

    Populate the vehicle year choices relative to the year the interview runs:

    Input (interview YAML)

question: |
What year was your vehicle made?
fields:
- Year: users[0].vehicles[0].year
datatype: integer
code: recent_years(past=25, future=1)

Example​

Populate the vehicle year choices relative to the year the interview runs:

Input (interview YAML)

question: |
What year was your vehicle made?
fields:
- Year: users[0].vehicles[0].year
datatype: integer
code: recent_years(past=25, future=1)

ALPeriodicAmount Objects​

class ALPeriodicAmount(DAObject)

Represents an amount (could be an income or an expense depending on the context) that reoccurs some times per year. E.g, to express a weekly period, use 52. The default is 1 (a year).

Attributes​

  • value str | float | Decimal - A number representing an amount of money accumulated during the times_per_year of this income.
  • times_per_year float | Decimal - Represents a number of the annual frequency of the income. E.g. 12 for a monthly income.
  • source str, optional - The "source" of the income, like a "job" or a "house".
  • display_name str, optional - If present, will have a translated string to show the user, as opposed to a raw english string from the program.

Example​

ALExpense inherits this calculation. With a gathered expense on the first person, convert it to a monthly amount:

Input (interview YAML)

modules:
- docassemble.ALToolbox.al_income
question: |
Monthly expenses
subquestion: |
${ currency(users[0].expenses[0].total(times_per_year=12)) }

__str__​

def __str__() -> str

Returns the income's total value as a string representation.

Returns​

The string representation of this income's total value.

total​

def total(times_per_year: float = 1) -> Decimal

Returns the income over the specified times_per_year.

To calculate .total(), an ALPeriodicAmount must have a .times_per_year and .value.

Arguments​

  • times_per_year float, optional - The frequency to convert the income to. Defaults to 1 (annual).

Returns​

  • Decimal - The calculated income amount for the specified frequency.

Example​

With users[0].expenses[0].value = 1000, .times_per_year = 12, and US English currency formatting:

Input (Mako)

${ currency(users[0].expenses[0].total(times_per_year=1)) }

Input (Jinja2)

{{ currency(users[0].expenses[0].total(times_per_year=1)) }}

Output

$12,000.00

ALIncome Objects​

class ALIncome(ALPeriodicAmount)

Represents an income which may have an hourly rate or a salary. Hourly rate incomes must include hours per period (times per year). Period is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year).

Attributes​

  • value str | float | Decimal - A number representing an amount of money accumulated during the times_per_year of this income.
  • times_per_year float | Decimal - Represents a number of the annual frequency of the income. E.g. 12 for a monthly income.
  • is_hourly bool, optional - True if the income is hourly.
  • hours_per_period float | Decimal, optional - If the income is hourly, the number of hours during the annual frequency of this job. E.g. if the annual frequency is 52 (weekly), the hours per week might be 50. That is, 50 hours per week. This attribute is required if .is_hourly is True.
  • source str, optional - The "source" of the income, like a "job" or a "house".
  • owner str, optional - Full name of the income's owner as a single string.

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].incomes[0], is a ALIncome.

Input (interview YAML)

objects:
- users[0].incomes: ALIncomeList.using(complete_attribute="complete")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].expenses.total(times_per_year=12)) }

SourceType​

_to_set​

def _to_set(s: Optional[Union[Set, List, str]]) -> Set

Convert various input types into a set of strings for source filtering.

Converts a str, list of strings, or set of strings into a set of strings, which can be used to filter items in ALIncome classes. This is for internal use meant to ensure that source input is always a set.

Arguments​

  • s Optional[Union[Set, List, str]] - The input to convert to a set. Can be None, a string, list of strings, or set of strings.

Returns​

A set of strings for filtering purposes.

_source_to_callable​

def _source_to_callable(
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Callable[[str], bool]

Create a filtering function from positive and negative source lists.

Combines both a positive and negative lists into a single set that should be tested for inclusion, creating a callable that can filter income sources.

Arguments​

  • source Optional[SourceType], optional - Sources to include in filtering. Defaults to None.
  • exclude_source Optional[SourceType], optional - Sources to exclude from filtering. Defaults to None.

Returns​

A callable function that takes a source string and returns True if it should be included based on the filtering criteria.

ALIncomeList Objects​

class ALIncomeList(DAList)

Represents a filterable DAList of incomes-type items.

This list expects its items to have the following attributes and methods:

  • source: Source identifier for filtering
  • owner: Owner name for filtering
  • times_per_year: Frequency of the income
  • value: Amount value
  • total(): Calculate total amount for a given frequency

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].incomes[0], is a ALIncome.

Input (interview YAML)

objects:
- users[0].incomes: ALIncomeList.using(complete_attribute="complete")
code: |
users[0].incomes.move_checks_to_list()
users[0].incomes.moved = True

ALJob Objects​

class ALJob(ALIncome)

Represents a single job that may be hourly or pay-period based.

The job can have a net and gross income figure, but it does not represent individual items like wages, tips or deductions that may appear on a paycheck--the user must enter the total amount for "net" and "gross" income for a given period.

Can be stored in an ALJobList.

Attributes​

  • value float | Decimal - A number representing an amount of money accumulated during the times_per_year of this income.
  • times_per_year float - Represents a number of the annual frequency of the value. E.g. 12 for a monthly value.
  • is_hourly bool, optional - Whether the gross total should be calculated based on hours worked per week.
  • hours_per_period float, optional - The number of hours during the annual frequency of this job. E.g. if the annual frequency is 52 (weekly), the hours per week might be 50. That is, 50 hours per week.
  • deduction float, optional - The amount of money deducted from the total value each period. If this job is hourly, deduction is still from each period, not each hour. Used to calculate the net income in net_income().
  • employer Individual, optional - A docassemble Individual object, employer.address is the address and employer.phone is the phone.

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].jobs[0], is a ALJob.

Input (interview YAML)

objects:
- users[0].jobs: ALJobList.using(complete_attribute="complete")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].jobs.net_total(times_per_year=12)) }

init​

def init(*pargs, **kwargs)

Initialize an ALJobList with ALJob as the default object type.

Arguments​

  • *pargs - Variable length argument list passed to parent class.
  • **kwargs - Arbitrary keyword arguments passed to parent class.

total​

def total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None,
owner: Optional[str] = None) -> Decimal

Returns the sum of the gross incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by source. source can be a string or a list.

times_per_year is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year).

Example​

With one gathered job in users[0].jobs, where users[0].jobs[0] has value=1000, deduction=200, times_per_year=12, is_hourly=False, and hours_per_period=40, and source="job", using US English currency formatting:

Input (Mako)

${ currency(users[0].jobs.total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].jobs.total(times_per_year=12)) }}

Output

$1,000.00

gross_total​

def gross_total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the sum of the gross incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by source. source can be a string or a list.

Arguments​

  • times_per_year float - The time period to divide the gross income by. Defaults to 1.
  • source Optional[SourceType] - The source of the jobs to include. Defaults to None.
  • exclude_source Optional[SourceType] - The source of the jobs to exclude. Defaults to None.

Returns​

The sum of the gross incomes of its ALJobs divided by the time times_per_year.

Example​

With one gathered job in users[0].jobs, where users[0].jobs[0] has value=1000, deduction=200, times_per_year=12, is_hourly=False, and hours_per_period=40, and source="job", using US English currency formatting:

Input (Mako)

${ currency(users[0].jobs.gross_total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].jobs.gross_total(times_per_year=12)) }}

Output

$1,000.00

net_total​

def net_total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the sum of the net incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by source. source can be a string or a list. Leaving out source will use all sources.

If the job is hourly, the net_total() may not be comparable to the gross_total().

Arguments​

  • times_per_year float - The time period to divide the net income by. Defaults to 1.
  • source Optional[SourceType] - The source of the jobs to include. Defaults to None.
  • exclude_source Optional[SourceType] - The source of the jobs to exclude. Defaults to None.

Returns​

The sum of the net incomes of its ALJobs divided by the time times_per_year.

Example​

With one gathered job in users[0].jobs, where users[0].jobs[0] has value=1000, deduction=200, times_per_year=12, is_hourly=False, and hours_per_period=40, and source="job", using US English currency formatting:

Input (Mako)

${ currency(users[0].jobs.net_total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].jobs.net_total(times_per_year=12)) }}

Output

$800.00

deductions​

def deductions(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the sum of the deductions of its ALJobs divided by the time times_per_year. You can filter the jobs by source. Leaving out source will use all sources.

Arguments​

  • times_per_year float - The time period to divide the deductions by. Defaults to 1.
  • source Optional[SourceType] - The source of the jobs to include. Defaults to None.
  • exclude_source Optional[SourceType] - The source of the jobs to exclude. Defaults to None.

Returns​

The sum of the deductions of its ALJobs divided by the time times_per_year.

Example​

With one gathered job in users[0].jobs, where users[0].jobs[0] has value=1000, deduction=200, times_per_year=12, is_hourly=False, and hours_per_period=40, and source="job", using US English currency formatting:

Input (Mako)

${ currency(users[0].jobs.deductions(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].jobs.deductions(times_per_year=12)) }}

Output

$200.00

ALExpenseList Objects​

class ALExpenseList(ALIncomeList)

A list of expenses.

Each element has: value: The monetary value of the expense source: The source category of the expense display_name: Human-readable name for display

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].expenses[0], is a ALExpense.

Input (interview YAML)

objects:
- users[0].expenses: ALExpenseList.using(complete_attribute="complete")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].assets.market_value()) }

total​

def total(times_per_year: float = 1) -> Decimal

Returns the .value attribute divided by the times per year you want to calculate. The value defaults to 0.

times_per_year is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year).

Arguments​

  • times_per_year float, optional - The number of times per year to calculate. Defaults to 1.

Returns​

  • Decimal - The .value attribute divided by the times per year.

Example​

With a gathered users[0].assets list containing one asset with market_value=10000, balance=2500, value=120, times_per_year=1, owner="Alex Rivera", and source="savings", in US English formatting:

Input (Mako)

${ currency(users[0].assets[0].total()) }

Input (Jinja2)

{{ currency(users[0].assets[0].total()) }}

Output

$120.00

equity​

def equity(loan_attribute="balance") -> Decimal

Returns the total equity in the asset (e.g., market value minus balance).

Arguments​

  • loan_attribute str, optional - The attribute of the asset to use as the loan value. Defaults to "balance".

Returns​

  • Decimal - The total equity in the asset.

Example​

With a gathered users[0].assets list containing one asset with market_value=10000, balance=2500, value=120, times_per_year=1, owner="Alex Rivera", and source="savings", in US English formatting:

Input (Mako)

${ currency(users[0].assets[0].equity()) }

Input (Jinja2)

{{ currency(users[0].assets[0].equity()) }}

Output

$7,500.00

ALAssetList Objects​

class ALAssetList(ALIncomeList)

A list of ALAssets. The total() of the list will be the total income earned, which may not be what you want for a list of assets. To get the total value of all assets, use the market_value() method.

Attributes​

  • market_value float | Decimal - Market value of the asset.
  • balance float | Decimal - Current balance of the account, e.g., like the balance in a checking account, but could also represent a loan amount.
  • value float | Decimal, optional - Represents the income the asset earns for a given times_per_year, such as interest earned in a checking account. If not defined, the income will be set to 0, to simplify representing the many common assets that do not earn any income.
  • times_per_year float, optional - Number of times per year the asset earns the income listed in the value attribute.
  • owner str, optional - Full name of the asset owner as a single string.
  • source str, optional - The "source" of the asset, like "vase".

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].assets[0], is a ALAsset.

Input (interview YAML)

objects:
- users[0].assets: ALAssetList.using(complete_attribute="complete")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].vehicles.market_value()) }

init​

def init(*pargs, **kwargs)

year_make_model​

def year_make_model(separator: str = " / ") -> str

Returns a string of the format year/make/model of the vehicle.

Triggers gathering those attributes and formats them as a single string.

Arguments​

  • separator str, optional - The separator between the year, make and model. Defaults to " / ".

Returns​

  • str - A formatted string combining year, make, and model of the vehicle.

Example​

With users[0].vehicles[0].year = 2020, .make = "Toyota", and .model = "Camry" on that vehicle:

Input (Mako)

${ users[0].vehicles[0].year_make_model() }

Input (Jinja2)

{{ users[0].vehicles[0].year_make_model() }}

Output

2020 / Toyota / Camry

ALVehicleList Objects​

class ALVehicleList(ALAssetList)

List of ALVehicles. Extends ALAssetList.

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].vehicles[0], is a ALVehicle.

Input (interview YAML)

objects:
- users[0].vehicles: ALVehicleList.using(complete_attribute="complete")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].transactions.total()) }

total​

def total() -> Decimal

If desired, to use as a ledger, values can be signed (mixed positive and negative). Setting transaction_type = 'expense' makes the value negative. Use min=0 in that case.

If you use signed values, be careful when placing in an ALIncomeList object. The total() method may return unexpected results in that case.

Returns​

The total value of the item, taking into account the transaction type.

Example​

With a gathered users[0].transactions list containing a receipt (value=100, source="deposit") and an expense (value=25, source="fee", transaction_type="expense"), in US English formatting:

Input (Mako)

${ currency(users[0].transactions[1].total()) }

Input (Jinja2)

{{ currency(users[0].transactions[1].total()) }}

Output

-$25.00

__str__​

def __str__() -> str

Returns the total as a formatted string

ALSimpleValueList Objects​

class ALSimpleValueList(DAList)

Represents a filterable DAList of ALSimpleValues.

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].transactions[0], is a ALSimpleValue.

Input (interview YAML)

objects:
- users[0].transactions: ALSimpleValueList.using(complete_attribute="value")
question: |
Review your information
subquestion: |
Total: ${ currency(users[0].itemized_jobs.net_total(times_per_year=12)) }

init​

def init(*pargs, **kwargs)

_item_value_per_times_per_year​

def _item_value_per_times_per_year(item: ALItemizedValue,
times_per_year: float = 1) -> Decimal

Given an ALItemizedValue and a times_per_year, returns the value accumulated by the item for that times_per_year, applying the attributes of the top-level ALItemizedJob, such as times_per_year and is_hourly as a default, and otherwise applying the attributes of the ALItemizedValue.

times_per_year is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year).

Arguments​

arg item {ALItemizedValue} Object containing the value and other props for an "in" or "out" ALItemizedJob item.

  • kwarg - times_per_year {float} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1.

total​

def total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Alias for ALItemizedJob.gross_total to integrate with ALIncomeList math.

Arguments​

  • times_per_year float - The time period to divide the gross total by. Defaults to 1.
  • source Optional[SourceType] - The source of the items to include. Defaults to None.
  • exclude_source Optional[SourceType] - The source of the items to exclude. Defaults to None.

Returns​

The gross total of the job.

Example​

With one gathered, non-hourly job in users[0].itemized_jobs, paid monthly (times_per_year=12, hours_per_period=40). Its to_add["wages"] is 1000 and to_subtract["taxes"] is 200, both with exists=True, is_hourly=False, and times_per_year=12. Use US English formatting:

Input (Mako)

${ currency(users[0].itemized_jobs[0].total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].itemized_jobs[0].total(times_per_year=12)) }}

Output

$1,000.00

gross_total​

def gross_total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the sum of positive values (payments) for a given times_per_year. You can filter the items by source. source can be a string or a list. If you use sources from deductions, they will be ignored.

Arguments​

  • times_per_year float, optional - Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Defaults to 1.
  • source str | List[str], optional - Source or list of sources of desired item(s). Defaults to None.
  • exclude_source str | List[str], optional - Source or list of sources to exclude from calculation. Defaults to None.

Returns​

  • Decimal - The sum of positive values for the given parameters.

Example​

With one gathered, non-hourly job in users[0].itemized_jobs, paid monthly (times_per_year=12, hours_per_period=40). Its to_add["wages"] is 1000 and to_subtract["taxes"] is 200, both with exists=True, is_hourly=False, and times_per_year=12. Use US English formatting:

Input (Mako)

${ currency(users[0].itemized_jobs[0].gross_total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].itemized_jobs[0].gross_total(times_per_year=12)) }}

Output

$1,000.00

deduction_total​

def deduction_total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the sum of money going out (normally, deductions like union dues) divided by a pay times_per_year as a positive value. You can filter the items by source. source can be a string or a list.

Arguments​

  • times_per_year float, optional - Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Defaults to 1.
  • source str | List[str], optional - Source or list of sources of desired item(s). Defaults to None.
  • exclude_source str | List[str], optional - Source or list of sources to exclude from calculation. Defaults to None.

Returns​

  • Decimal - The sum of deductions for the given parameters as a positive value.

Example​

With one gathered, non-hourly job in users[0].itemized_jobs, paid monthly (times_per_year=12, hours_per_period=40). Its to_add["wages"] is 1000 and to_subtract["taxes"] is 200, both with exists=True, is_hourly=False, and times_per_year=12. Use US English formatting:

Input (Mako)

${ currency(users[0].itemized_jobs[0].deduction_total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].itemized_jobs[0].deduction_total(times_per_year=12)) }}

Output

$200.00

net_total​

def net_total(times_per_year: float = 1,
source: Optional[SourceType] = None,
exclude_source: Optional[SourceType] = None) -> Decimal

Returns the net (gross minus deductions) value of the job divided by times_per_year. You can filter the items by source. source can be a string or a list. E.g. "full time" or ["full time", "union dues"]

Arguments​

  • times_per_year float, optional - Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Defaults to 1.
  • source str | List[str], optional - Source or list of sources of desired item(s). Defaults to None.
  • exclude_source str | List[str], optional - Source or list of sources to exclude from calculation. Defaults to None.

Returns​

  • Decimal - The net value (gross minus deductions) for the given parameters.

Example​

With one gathered, non-hourly job in users[0].itemized_jobs, paid monthly (times_per_year=12, hours_per_period=40). Its to_add["wages"] is 1000 and to_subtract["taxes"] is 200, both with exists=True, is_hourly=False, and times_per_year=12. Use US English formatting:

Input (Mako)

${ currency(users[0].itemized_jobs[0].net_total(times_per_year=12)) }

Input (Jinja2)

{{ currency(users[0].itemized_jobs[0].net_total(times_per_year=12)) }}

Output

$800.00

employer_name_address_phone​

def employer_name_address_phone() -> str

Returns concatenation of employer name and, if they exist, employer address and phone number.

Returns​

A string containing the employer's name, address, and phone number.

Example​

After gathering the itemized job’s employer information:

Input (Mako)

${ users[0].itemized_jobs[0].employer_name_address_phone() }

Input (Jinja2)

{{ users[0].itemized_jobs[0].employer_name_address_phone() }}

normalized_hours​

def normalized_hours(times_per_year: float = 1) -> float

Returns the normalized number of hours worked in a given times_per_year, based on the self.hours_per_period and self.times_per_year attributes.

For example, if the person works 10 hours a week, it will return 520 when the times_per_year parameter is 1.

Arguments​

  • times_per_year float - The time period to normalize the hours to. Defaults to 1.

Returns​

The normalized number of hours worked in the given time period.

Example​

With one gathered, non-hourly job in users[0].itemized_jobs, paid monthly (times_per_year=12, hours_per_period=40). Its to_add["wages"] is 1000 and to_subtract["taxes"] is 200, both with exists=True, is_hourly=False, and times_per_year=12. Use US English formatting:

Input (Mako)

${ users[0].itemized_jobs[0].normalized_hours(times_per_year=1) }

Input (Jinja2)

{{ users[0].itemized_jobs[0].normalized_hours(times_per_year=1) }}

Output

480.0

ALItemizedJobList Objects​

class ALItemizedJobList(DAList)

Represents a list of ALItemizedJobs that can have both payments and money out. This is a less common way of reporting income.

Example​

In an AssemblyLine interview, users is an ALPeopleList and users[0] is an ALIndividual. Include docassemble.ALToolbox:al_income.yml for the income questions, then attach this list to the first person: Each entry, such as users[0].itemized_jobs[0], is a ALItemizedJob.

Input (interview YAML)

objects:
- users[0].itemized_jobs: ALItemizedJobList.using(complete_attribute="complete")