the-exchequer-tally 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- the_exchequer_tally-0.1.3/.editorconfig +15 -0
- the_exchequer_tally-0.1.3/.github/CODEOWNERS +1 -0
- the_exchequer_tally-0.1.3/.github/dependabot.yml +32 -0
- the_exchequer_tally-0.1.3/.github/workflows/ci.yml +49 -0
- the_exchequer_tally-0.1.3/.github/workflows/codeql.yml +38 -0
- the_exchequer_tally-0.1.3/.gitignore +22 -0
- the_exchequer_tally-0.1.3/.mailmap +4 -0
- the_exchequer_tally-0.1.3/DISCLAIMER.md +42 -0
- the_exchequer_tally-0.1.3/LICENSE +21 -0
- the_exchequer_tally-0.1.3/PKG-INFO +119 -0
- the_exchequer_tally-0.1.3/README.md +92 -0
- the_exchequer_tally-0.1.3/RELEASE_NOTES.md +32 -0
- the_exchequer_tally-0.1.3/SECURITY.md +15 -0
- the_exchequer_tally-0.1.3/edwinnixon/__init__.py +53 -0
- the_exchequer_tally-0.1.3/edwinnixon/benchmark_rule.py +173 -0
- the_exchequer_tally-0.1.3/edwinnixon/cli.py +147 -0
- the_exchequer_tally-0.1.3/edwinnixon/corporate_tax.py +150 -0
- the_exchequer_tally-0.1.3/edwinnixon/distribution_statement.py +85 -0
- the_exchequer_tally-0.1.3/edwinnixon/franking_account.py +215 -0
- the_exchequer_tally-0.1.3/edwinnixon/py.typed +0 -0
- the_exchequer_tally-0.1.3/pyproject.toml +64 -0
- the_exchequer_tally-0.1.3/tests/test_cli_types.py +30 -0
- the_exchequer_tally-0.1.3/tests/test_distribution_validation.py +37 -0
- the_exchequer_tally-0.1.3/tests/test_edwinnixon.py +535 -0
- the_exchequer_tally-0.1.3/tests/test_package_identity.py +47 -0
- the_exchequer_tally-0.1.3/uv.lock +666 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
indent_style = space
|
|
9
|
+
indent_size = 4
|
|
10
|
+
|
|
11
|
+
[*.{yml,yaml,json,md,toml}]
|
|
12
|
+
indent_size = 2
|
|
13
|
+
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ryanduguid
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
github-actions:
|
|
9
|
+
patterns:
|
|
10
|
+
- "*"
|
|
11
|
+
codeql-action:
|
|
12
|
+
patterns:
|
|
13
|
+
- "github/codeql-action*"
|
|
14
|
+
ignore:
|
|
15
|
+
# ADR-0001: the release-policy pin is an immutable full commit SHA,
|
|
16
|
+
# advanced only by a reviewed migration that also updates the pin
|
|
17
|
+
# assertion and verifies attestations against the new signer workflow.
|
|
18
|
+
# Dependabot can do neither, so its bumps are refused by the pin tests
|
|
19
|
+
# and sit red forever. Pin drift is tracked by release-policy's canary
|
|
20
|
+
# audit instead.
|
|
21
|
+
- dependency-name: "ryanduguid/release-policy/.github/workflows/*"
|
|
22
|
+
- package-ecosystem: "uv"
|
|
23
|
+
directory: "/"
|
|
24
|
+
schedule:
|
|
25
|
+
interval: "weekly"
|
|
26
|
+
cooldown:
|
|
27
|
+
default-days: 7
|
|
28
|
+
open-pull-requests-limit: 2
|
|
29
|
+
groups:
|
|
30
|
+
python:
|
|
31
|
+
patterns:
|
|
32
|
+
- "*"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: tests-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: pytest
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
python: ["3.10", "3.12", "3.13"]
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
timeout-minutes: 15
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python }}
|
|
33
|
+
- name: install the locked toolchain
|
|
34
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
35
|
+
with:
|
|
36
|
+
version: "0.12.0"
|
|
37
|
+
enable-cache: true
|
|
38
|
+
- name: Ruff
|
|
39
|
+
run: uv run --locked --extra dev ruff check edwinnixon tests
|
|
40
|
+
env:
|
|
41
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
42
|
+
- name: Typecheck
|
|
43
|
+
run: uv run --locked --extra dev mypy edwinnixon
|
|
44
|
+
env:
|
|
45
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
46
|
+
- name: Run tests
|
|
47
|
+
run: uv run --locked --extra dev pytest -q
|
|
48
|
+
env:
|
|
49
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "23 3 * * 1"
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
analyze:
|
|
17
|
+
name: Analyze Python
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 30
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
security-events: write # Upload CodeQL results for this job only.
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check out source
|
|
25
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
|
|
29
|
+
- name: Initialise CodeQL
|
|
30
|
+
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
|
31
|
+
with:
|
|
32
|
+
languages: python
|
|
33
|
+
build-mode: none
|
|
34
|
+
|
|
35
|
+
- name: Perform CodeQL analysis
|
|
36
|
+
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
|
37
|
+
with:
|
|
38
|
+
category: "/language:python"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
|
|
11
|
+
# Unit test / coverage
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# Environments
|
|
17
|
+
.env
|
|
18
|
+
.venv
|
|
19
|
+
env/
|
|
20
|
+
venv/
|
|
21
|
+
.env.*
|
|
22
|
+
!.env.example
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Disclaimer
|
|
2
|
+
|
|
3
|
+
The Exchequer Tally tests base rate entity status, tracks a franking account
|
|
4
|
+
ledger, and applies the Division 203 benchmark rule for Australian companies.
|
|
5
|
+
It is not tax, legal, accounting, financial, investment, BAS-agent,
|
|
6
|
+
registered-tax-agent, or assurance advice. It is not an assessment, a private
|
|
7
|
+
ruling, or a determination.
|
|
8
|
+
|
|
9
|
+
This project is not affiliated with, sponsored by, endorsed by, or approved by:
|
|
10
|
+
|
|
11
|
+
- the Australian Taxation Office
|
|
12
|
+
- the Commonwealth of Australia
|
|
13
|
+
- any state or territory revenue office
|
|
14
|
+
- Chartered Accountants Australia and New Zealand
|
|
15
|
+
- the Australian Securities and Investments Commission
|
|
16
|
+
- any software vendor
|
|
17
|
+
|
|
18
|
+
Outputs can be wrong, incomplete, stale, or unsuitable for a given set of
|
|
19
|
+
facts. Corporate tax rates, aggregated-turnover thresholds, the passive-income
|
|
20
|
+
test, ATO guidance and administrative practice change, and the engine sees
|
|
21
|
+
only the facts it is handed. Confirm every rate, threshold and consequence
|
|
22
|
+
against the current law and the entity's facts before acting, and leave
|
|
23
|
+
lodgment decisions with a registered practitioner.
|
|
24
|
+
|
|
25
|
+
A franking account balance produced here is a workpaper figure rebuilt from
|
|
26
|
+
the entries supplied. It is not the company's franking account for statutory
|
|
27
|
+
purposes and it does not replace the company's own records. A distribution
|
|
28
|
+
statement built by this tool populates the fields required by s 202-75 and
|
|
29
|
+
s 202-80 as a review helper. It is not a lodgment and not a compliance
|
|
30
|
+
certificate.
|
|
31
|
+
|
|
32
|
+
Nothing here lodges a company tax return, a franking account tax return, or
|
|
33
|
+
any other official form, posts journals, pays tax, or sends shareholder
|
|
34
|
+
correspondence. Those remain authorised human actions.
|
|
35
|
+
|
|
36
|
+
Do not publish private tax records, TFNs, client-identifying ABNs, bank
|
|
37
|
+
details, identity documents, client files, or other sensitive personal
|
|
38
|
+
information in issues, pull requests, examples, tests, or repository content.
|
|
39
|
+
Fixtures in this repository are fabricated.
|
|
40
|
+
|
|
41
|
+
See [LICENSE](LICENSE) for copyright and [SECURITY.md](SECURITY.md) for
|
|
42
|
+
vulnerability reporting.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ryan Duguid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: the-exchequer-tally
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Corporate tax rate verification, franking account ledger tracking, and Division 203 benchmark rule compliance for Australian companies.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ryanduguid/australian-accounting/tree/main/packages/the-exchequer-tally
|
|
6
|
+
Project-URL: Repository, https://github.com/ryanduguid/australian-accounting/tree/main/packages/the-exchequer-tally
|
|
7
|
+
Project-URL: Issues, https://github.com/ryanduguid/australian-accounting/issues
|
|
8
|
+
Author-email: Ryan Duguid <ryan@duguid.com.au>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
22
|
+
Requires-Dist: mypy>=1.14; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# The Exchequer Tally
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
+----------------------------------------------------------------------+
|
|
32
|
+
| TheExchequerTally |
|
|
33
|
+
+----------------------------------------------------------------------+
|
|
34
|
+
| Corporate tax rate, franking and Div 203 checks |
|
|
35
|
+
+----------------------------------+-----------------------------------+
|
|
36
|
+
| DR what it gives you | CR what it needs |
|
|
37
|
+
+----------------------------------+-----------------------------------+
|
|
38
|
+
| Base Rate Entity FY testing | turnover and passive income |
|
|
39
|
+
| franking account ledger | entity ACN and dividend data |
|
|
40
|
+
| dividend distribution statements | - |
|
|
41
|
+
+----------------------------------+-----------------------------------+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
[](https://www.python.org/)
|
|
45
|
+
[](https://github.com/ryanduguid/australian-accounting/actions/workflows/ci-the-exchequer-tally.yml)
|
|
46
|
+
[](https://pypi.org/project/the-exchequer-tally/)
|
|
47
|
+
[](https://opensource.org/licenses/MIT)
|
|
48
|
+
[](https://www.legislation.gov.au/C2004A05138/latest/text)
|
|
49
|
+
|
|
50
|
+
**Corporate tax rate verification, franking account ledger tracking, and Division 203 benchmark rule compliance for Australian private and public companies.**
|
|
51
|
+
|
|
52
|
+
**Package lifecycle:** published. Install `the-exchequer-tally` from PyPI.
|
|
53
|
+
|
|
54
|
+
The `australian-accounting` repository contains the maintained source. The
|
|
55
|
+
`the-exchequer-tally` distribution and command match the project identity. The
|
|
56
|
+
`edwinnixon` import package remains unchanged, so internal Python imports do not
|
|
57
|
+
need a rename.
|
|
58
|
+
|
|
59
|
+
Release: [`v0.1.3`](https://github.com/ryanduguid/australian-accounting/releases/tag/the-exchequer-tally/v0.1.3).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Core Features
|
|
64
|
+
|
|
65
|
+
- **Base Rate Entity (BRE) Testing**: Deterministic assessment under *s 23AA & s 23AB Income Tax Rates Act 1986* (evaluating aggregated turnover thresholds and Base Rate Entity Passive Income ratios).
|
|
66
|
+
- **Franking Account Ledger (FAB)**: Complete balance management under *Part 3-6 ITAA 1997*, tracking PAYG instalments, company tax payments, dividends paid/received, and tax refunds.
|
|
67
|
+
- **Franking Deficit Tax (FDT) & Offset Penalty**: Evaluates FDT liability under *s 205-45* and calculates the 30% tax offset reduction penalty under *s 205-70(6)* where the deficit exceeds 10% of annual credits.
|
|
68
|
+
- **Division 203 Benchmark Rule Engine**: Detects over-franking tax (*s 203-50(1)*) and franking debit shortfalls (*s 203-50(2)*) across distributions in a franking period.
|
|
69
|
+
- **Dividend Distribution Statements**: Builds the statement fields required by *s 202-75 / s 202-80*. This is a review helper, not a lodgment and not a compliance certificate.
|
|
70
|
+
|
|
71
|
+
## Not advice
|
|
72
|
+
|
|
73
|
+
Nothing this engine produces is tax, legal or financial advice, an assessment
|
|
74
|
+
or a determination. Outputs are review aids: confirm every rate, threshold and
|
|
75
|
+
consequence against the current law and the entity's facts before acting, and
|
|
76
|
+
leave lodgment decisions with a registered practitioner.
|
|
77
|
+
|
|
78
|
+
Full boundary statement: [DISCLAIMER.md](DISCLAIMER.md).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Quickstart
|
|
83
|
+
|
|
84
|
+
### Installation
|
|
85
|
+
```bash
|
|
86
|
+
pip install the-exchequer-tally
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### CLI Usage
|
|
90
|
+
```bash
|
|
91
|
+
# Evaluate Base Rate Entity (BRE) status for FY2025
|
|
92
|
+
the-exchequer-tally bre-test --fy 2025 --turnover 4500000 --assessable 800000 --passive 120000
|
|
93
|
+
|
|
94
|
+
# Generate a dividend distribution statement
|
|
95
|
+
the-exchequer-tally dist-statement --entity "Acme Pty Ltd" --acn "123456789" --recipient "Jane Doe" --amount 15000 --franking-pct 100 --tax-rate 0.25
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Statutory Ground Truth & Test Harness
|
|
101
|
+
|
|
102
|
+
All mathematical operations execute via `decimal.Decimal` fixed-point arithmetic to guarantee zero floating-point drift across corporate tax and franking schedules.
|
|
103
|
+
|
|
104
|
+
| Statutory Domain | Primary Authority | Verification Invariant |
|
|
105
|
+
| :--- | :--- | :--- |
|
|
106
|
+
| **Base Rate Entity Status** | *Income Tax Rates Act 1986* s 23AA | BRE rate bounded by the year's aggregated-turnover threshold ($25M for FY2018, $50M from FY2019) and BREPI <= 80% compared exactly. |
|
|
107
|
+
| **Franking Credits & Debits** | *ITAA 1997* s 205-15, s 205-30 | Cent-exact ledger of credits and debits (dates recorded for the workpaper; balances are order-independent sums). |
|
|
108
|
+
| **FDT Offset Reduction** | *ITAA 1997* s 205-45, s 205-70(6) | Exact 30% offset reduction penalty applied when deficit exceeds 10% threshold. |
|
|
109
|
+
| **Benchmark Rule** | *ITAA 1997* ss 203-25 to 203-55 | Benchmark set by the first frankable distribution in the franking period (*s 203-30*), then one deterministic shortfall or over-franking result per later distribution. |
|
|
110
|
+
| **Distribution Statements** | *ITAA 1997* ss 202-75, 202-80 | Precise franking credit formula: `Distribution * (Rate / (1 - Rate)) * Franking%`. |
|
|
111
|
+
|
|
112
|
+
### Automated Test Suite
|
|
113
|
+
- Run the full suite: `uv run --locked --extra dev pytest` (or `pip install .[dev]` then `pytest`; the configured coverage add-on needs the dev extras)
|
|
114
|
+
- The suite covers BRE eligibility, FDT penalty triggers, benchmark-rule checks, and distribution-statement generation. Do not treat a static badge as live coverage.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Licence
|
|
119
|
+
MIT License. Created by Ryan Duguid.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# The Exchequer Tally
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
+----------------------------------------------------------------------+
|
|
5
|
+
| TheExchequerTally |
|
|
6
|
+
+----------------------------------------------------------------------+
|
|
7
|
+
| Corporate tax rate, franking and Div 203 checks |
|
|
8
|
+
+----------------------------------+-----------------------------------+
|
|
9
|
+
| DR what it gives you | CR what it needs |
|
|
10
|
+
+----------------------------------+-----------------------------------+
|
|
11
|
+
| Base Rate Entity FY testing | turnover and passive income |
|
|
12
|
+
| franking account ledger | entity ACN and dividend data |
|
|
13
|
+
| dividend distribution statements | - |
|
|
14
|
+
+----------------------------------+-----------------------------------+
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
[](https://www.python.org/)
|
|
18
|
+
[](https://github.com/ryanduguid/australian-accounting/actions/workflows/ci-the-exchequer-tally.yml)
|
|
19
|
+
[](https://pypi.org/project/the-exchequer-tally/)
|
|
20
|
+
[](https://opensource.org/licenses/MIT)
|
|
21
|
+
[](https://www.legislation.gov.au/C2004A05138/latest/text)
|
|
22
|
+
|
|
23
|
+
**Corporate tax rate verification, franking account ledger tracking, and Division 203 benchmark rule compliance for Australian private and public companies.**
|
|
24
|
+
|
|
25
|
+
**Package lifecycle:** published. Install `the-exchequer-tally` from PyPI.
|
|
26
|
+
|
|
27
|
+
The `australian-accounting` repository contains the maintained source. The
|
|
28
|
+
`the-exchequer-tally` distribution and command match the project identity. The
|
|
29
|
+
`edwinnixon` import package remains unchanged, so internal Python imports do not
|
|
30
|
+
need a rename.
|
|
31
|
+
|
|
32
|
+
Release: [`v0.1.3`](https://github.com/ryanduguid/australian-accounting/releases/tag/the-exchequer-tally/v0.1.3).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Core Features
|
|
37
|
+
|
|
38
|
+
- **Base Rate Entity (BRE) Testing**: Deterministic assessment under *s 23AA & s 23AB Income Tax Rates Act 1986* (evaluating aggregated turnover thresholds and Base Rate Entity Passive Income ratios).
|
|
39
|
+
- **Franking Account Ledger (FAB)**: Complete balance management under *Part 3-6 ITAA 1997*, tracking PAYG instalments, company tax payments, dividends paid/received, and tax refunds.
|
|
40
|
+
- **Franking Deficit Tax (FDT) & Offset Penalty**: Evaluates FDT liability under *s 205-45* and calculates the 30% tax offset reduction penalty under *s 205-70(6)* where the deficit exceeds 10% of annual credits.
|
|
41
|
+
- **Division 203 Benchmark Rule Engine**: Detects over-franking tax (*s 203-50(1)*) and franking debit shortfalls (*s 203-50(2)*) across distributions in a franking period.
|
|
42
|
+
- **Dividend Distribution Statements**: Builds the statement fields required by *s 202-75 / s 202-80*. This is a review helper, not a lodgment and not a compliance certificate.
|
|
43
|
+
|
|
44
|
+
## Not advice
|
|
45
|
+
|
|
46
|
+
Nothing this engine produces is tax, legal or financial advice, an assessment
|
|
47
|
+
or a determination. Outputs are review aids: confirm every rate, threshold and
|
|
48
|
+
consequence against the current law and the entity's facts before acting, and
|
|
49
|
+
leave lodgment decisions with a registered practitioner.
|
|
50
|
+
|
|
51
|
+
Full boundary statement: [DISCLAIMER.md](DISCLAIMER.md).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Quickstart
|
|
56
|
+
|
|
57
|
+
### Installation
|
|
58
|
+
```bash
|
|
59
|
+
pip install the-exchequer-tally
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### CLI Usage
|
|
63
|
+
```bash
|
|
64
|
+
# Evaluate Base Rate Entity (BRE) status for FY2025
|
|
65
|
+
the-exchequer-tally bre-test --fy 2025 --turnover 4500000 --assessable 800000 --passive 120000
|
|
66
|
+
|
|
67
|
+
# Generate a dividend distribution statement
|
|
68
|
+
the-exchequer-tally dist-statement --entity "Acme Pty Ltd" --acn "123456789" --recipient "Jane Doe" --amount 15000 --franking-pct 100 --tax-rate 0.25
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Statutory Ground Truth & Test Harness
|
|
74
|
+
|
|
75
|
+
All mathematical operations execute via `decimal.Decimal` fixed-point arithmetic to guarantee zero floating-point drift across corporate tax and franking schedules.
|
|
76
|
+
|
|
77
|
+
| Statutory Domain | Primary Authority | Verification Invariant |
|
|
78
|
+
| :--- | :--- | :--- |
|
|
79
|
+
| **Base Rate Entity Status** | *Income Tax Rates Act 1986* s 23AA | BRE rate bounded by the year's aggregated-turnover threshold ($25M for FY2018, $50M from FY2019) and BREPI <= 80% compared exactly. |
|
|
80
|
+
| **Franking Credits & Debits** | *ITAA 1997* s 205-15, s 205-30 | Cent-exact ledger of credits and debits (dates recorded for the workpaper; balances are order-independent sums). |
|
|
81
|
+
| **FDT Offset Reduction** | *ITAA 1997* s 205-45, s 205-70(6) | Exact 30% offset reduction penalty applied when deficit exceeds 10% threshold. |
|
|
82
|
+
| **Benchmark Rule** | *ITAA 1997* ss 203-25 to 203-55 | Benchmark set by the first frankable distribution in the franking period (*s 203-30*), then one deterministic shortfall or over-franking result per later distribution. |
|
|
83
|
+
| **Distribution Statements** | *ITAA 1997* ss 202-75, 202-80 | Precise franking credit formula: `Distribution * (Rate / (1 - Rate)) * Franking%`. |
|
|
84
|
+
|
|
85
|
+
### Automated Test Suite
|
|
86
|
+
- Run the full suite: `uv run --locked --extra dev pytest` (or `pip install .[dev]` then `pytest`; the configured coverage add-on needs the dev extras)
|
|
87
|
+
- The suite covers BRE eligibility, FDT penalty triggers, benchmark-rule checks, and distribution-statement generation. Do not treat a static badge as live coverage.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Licence
|
|
92
|
+
MIT License. Created by Ryan Duguid.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# v0.1.3
|
|
2
|
+
|
|
3
|
+
This is the first PyPI release of `the-exchequer-tally`.
|
|
4
|
+
|
|
5
|
+
- Move the maintained source to `packages/the-exchequer-tally` in the
|
|
6
|
+
`australian-accounting` monorepo.
|
|
7
|
+
- Publish through `release-the-exchequer-tally.yml`, using the monorepo's
|
|
8
|
+
namespaced, attested release workflow.
|
|
9
|
+
- Preserve the v0.1.2 corporate-tax, franking-ledger and Division 203 behavior.
|
|
10
|
+
|
|
11
|
+
# v0.1.2
|
|
12
|
+
|
|
13
|
+
The repository's [GitHub Releases](https://github.com/ryanduguid/TheExchequerTally/releases) page is the canonical release history. A separate changelog is intentionally not maintained.
|
|
14
|
+
|
|
15
|
+
Prepared 0.1.2 notes. No PyPI distribution has been published; this source-only
|
|
16
|
+
project currently installs from a clone. The statutory corrections below were
|
|
17
|
+
found by an adversarially verified audit and checked against the legislation
|
|
18
|
+
text on legislation.gov.au:
|
|
19
|
+
|
|
20
|
+
- The maximum franking rate now applies the CURRENT year's rate scale to the prior year's amounts, per the s 995-1 ITAA 1997 definition of corporate tax rate for imputation purposes. The old code applied the prior year's scale, over-stating the rate by 1.0 to 1.5 percentage points across the 2020-21 and 2021-22 transitions.
|
|
21
|
+
- The FY2018 Base Rate Entity turnover threshold is $25 million (Enterprise Tax Plan Act 2017 Sch 1 Pt 2); $50 million applies from FY2019.
|
|
22
|
+
- The s 205-70 FDT offset reduction no longer switches off when zero franking credits arose in the year: with zero credits, any deficit exceeds 10 percent of them.
|
|
23
|
+
- The franking ledger's item 3 debit is the UNDER-franking debit (s 203-50(2) shortfall); over-franking tax is a tax liability, not a franking debit. New helpers record the under-franking debit and the s 205-15 FDT-liability credit so multi-year balances reconcile.
|
|
24
|
+
- The BREPI 80 percent test compares exactly instead of on a 2dp-rounded ratio; the franking percentage caps at 100; the benchmark comparison works in dollars at each event's own rate; the stated franking credit rounds down so it never exceeds the s 202-60 maximum; negative and out-of-range inputs are refused.
|
|
25
|
+
|
|
26
|
+
Also: one version source (pyproject) with `__version__` read from package
|
|
27
|
+
metadata, project URLs and classifiers, mypy enforced in CI (was advisory) with
|
|
28
|
+
Python 3.13 added, CodeQL and deduplicated Dependabot config. The source project
|
|
29
|
+
did not yet have the named publisher and compatibility contract required for a
|
|
30
|
+
release workflow; v0.1.3 supplies them from the monorepo.
|
|
31
|
+
|
|
32
|
+
Not advice. Outputs are review aids for a qualified professional, not determinations.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes are applied to the latest version on the default branch.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Use this repository's private vulnerability-reporting feature (Security > Report a vulnerability). Do not open a public issue or pull request for a suspected vulnerability.
|
|
10
|
+
|
|
11
|
+
Include a clear description, reproduction steps using fabricated data, likely impact, and any suggested mitigation. Never include client, taxpayer, employee, payroll, access-token or other sensitive data.
|
|
12
|
+
|
|
13
|
+
A valid report will be acknowledged within seven days. The fix and disclosure timeline will be agreed with the reporter.
|
|
14
|
+
|
|
15
|
+
If GitHub private reporting is not visible, enable it in repository settings rather than creating a public inbox.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The Exchequer Tally: corporate tax rate, franking account and Division 203
|
|
3
|
+
benchmark engine for Australian companies. The distribution is
|
|
4
|
+
`the-exchequer-tally`; the import package remains `edwinnixon`.
|
|
5
|
+
|
|
6
|
+
Outputs are review aids, not tax advice or determinations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from importlib.metadata import PackageNotFoundError, version as _dist_version
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
__version__ = _dist_version("the-exchequer-tally")
|
|
13
|
+
except PackageNotFoundError: # running from a source tree without installation
|
|
14
|
+
__version__ = "0.0.0.dev0"
|
|
15
|
+
__author__ = "Ryan Duguid"
|
|
16
|
+
|
|
17
|
+
from .corporate_tax import (
|
|
18
|
+
CorporateTaxRate,
|
|
19
|
+
BaseRateEntityTest,
|
|
20
|
+
determine_corporate_tax_rate,
|
|
21
|
+
determine_max_franking_rate,
|
|
22
|
+
)
|
|
23
|
+
from .franking_account import (
|
|
24
|
+
FrankingAccount,
|
|
25
|
+
FrankingEntry,
|
|
26
|
+
FrankingEntryType,
|
|
27
|
+
FrankingDeficitResult,
|
|
28
|
+
)
|
|
29
|
+
from .benchmark_rule import (
|
|
30
|
+
BenchmarkRuleValidator,
|
|
31
|
+
DistributionEvent,
|
|
32
|
+
BenchmarkRuleViolation,
|
|
33
|
+
)
|
|
34
|
+
from .distribution_statement import (
|
|
35
|
+
DistributionStatement,
|
|
36
|
+
generate_distribution_statement,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"CorporateTaxRate",
|
|
41
|
+
"BaseRateEntityTest",
|
|
42
|
+
"determine_corporate_tax_rate",
|
|
43
|
+
"determine_max_franking_rate",
|
|
44
|
+
"FrankingAccount",
|
|
45
|
+
"FrankingEntry",
|
|
46
|
+
"FrankingEntryType",
|
|
47
|
+
"FrankingDeficitResult",
|
|
48
|
+
"BenchmarkRuleValidator",
|
|
49
|
+
"DistributionEvent",
|
|
50
|
+
"BenchmarkRuleViolation",
|
|
51
|
+
"DistributionStatement",
|
|
52
|
+
"generate_distribution_statement",
|
|
53
|
+
]
|