lodgment-calendar 0.1.0__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.
Files changed (36) hide show
  1. lodgment_calendar-0.1.0/.gitignore +31 -0
  2. lodgment_calendar-0.1.0/CITATION.cff +16 -0
  3. lodgment_calendar-0.1.0/DISCLAIMER.md +26 -0
  4. lodgment_calendar-0.1.0/LICENSE +105 -0
  5. lodgment_calendar-0.1.0/MANIFEST.in +6 -0
  6. lodgment_calendar-0.1.0/NOTICE +20 -0
  7. lodgment_calendar-0.1.0/PKG-INFO +177 -0
  8. lodgment_calendar-0.1.0/README.md +145 -0
  9. lodgment_calendar-0.1.0/RELEASE_NOTES.md +19 -0
  10. lodgment_calendar-0.1.0/RELEASING.md +20 -0
  11. lodgment_calendar-0.1.0/SECURITY.md +15 -0
  12. lodgment_calendar-0.1.0/docs/primary-source-review-2026-10-20.md +261 -0
  13. lodgment_calendar-0.1.0/llms.txt +27 -0
  14. lodgment_calendar-0.1.0/lodgment_calendar.egg-info/PKG-INFO +177 -0
  15. lodgment_calendar-0.1.0/lodgment_calendar.egg-info/SOURCES.txt +34 -0
  16. lodgment_calendar-0.1.0/lodgment_calendar.egg-info/dependency_links.txt +1 -0
  17. lodgment_calendar-0.1.0/lodgment_calendar.egg-info/requires.txt +10 -0
  18. lodgment_calendar-0.1.0/lodgment_calendar.egg-info/top_level.txt +1 -0
  19. lodgment_calendar-0.1.0/lodgmentcalendar/__init__.py +11 -0
  20. lodgment_calendar-0.1.0/lodgmentcalendar/_version.py +1 -0
  21. lodgment_calendar-0.1.0/lodgmentcalendar/due_dates.py +259 -0
  22. lodgment_calendar-0.1.0/lodgmentcalendar/holidays.py +127 -0
  23. lodgment_calendar-0.1.0/lodgmentcalendar/py.typed +0 -0
  24. lodgment_calendar-0.1.0/lodgmentcalendar/returns.py +300 -0
  25. lodgment_calendar-0.1.0/lodgmentcalendar/rules.py +225 -0
  26. lodgment_calendar-0.1.0/lodgmentcalendar/statements.py +133 -0
  27. lodgment_calendar-0.1.0/pyproject.toml +78 -0
  28. lodgment_calendar-0.1.0/setup.cfg +4 -0
  29. lodgment_calendar-0.1.0/tests/test_activity_statements.py +221 -0
  30. lodgment_calendar-0.1.0/tests/test_caller_holidays.py +108 -0
  31. lodgment_calendar-0.1.0/tests/test_holidays.py +84 -0
  32. lodgment_calendar-0.1.0/tests/test_income_tax_returns.py +414 -0
  33. lodgment_calendar-0.1.0/tests/test_inputs.py +72 -0
  34. lodgment_calendar-0.1.0/tests/test_invariants.py +112 -0
  35. lodgment_calendar-0.1.0/tests/test_package_identity.py +37 -0
  36. lodgment_calendar-0.1.0/uv.lock +286 -0
@@ -0,0 +1,31 @@
1
+ # Client and taxpayer data never belongs in this repository.
2
+ client-data/
3
+ clients/
4
+ ledgers/
5
+ exports/
6
+ *.ofx
7
+ *.qbo
8
+ *.xlsx
9
+ *.xls
10
+ *.csv
11
+ !examples/**
12
+ !tests/fixtures/**
13
+
14
+ # Credentials
15
+ .env
16
+ .env.*
17
+ *.pem
18
+ *.key
19
+
20
+ # Python
21
+ __pycache__/
22
+ *.py[cod]
23
+ *.egg-info/
24
+ build/
25
+ dist/
26
+ .venv/
27
+ .pytest_cache/
28
+ .ruff_cache/
29
+ .coverage
30
+ coverage.xml
31
+ htmlcov/
@@ -0,0 +1,16 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software in research or industry applications, please cite it as below."
3
+ authors:
4
+ - family-names: Duguid
5
+ given-names: Ryan
6
+ title: "lodgment-calendar: ATO lodgment program due dates for BAS, IAS and income tax returns. Preparation aid, not a determination."
7
+ version: 0.1.0
8
+ url: "https://github.com/ryanduguid/australian-accounting/tree/main/packages/lodgment-calendar"
9
+ repository-code: "https://github.com/ryanduguid/australian-accounting/tree/main/packages/lodgment-calendar"
10
+ license-url: "https://github.com/ryanduguid/australian-accounting/blob/main/packages/lodgment-calendar/LICENSE"
11
+ keywords:
12
+ - lodgment-program
13
+ - bas
14
+ - tax-agent
15
+ - bas-agent
16
+ - australia
@@ -0,0 +1,26 @@
1
+ # Disclaimer
2
+
3
+ Ryan Duguid is not a registered tax agent or BAS agent. Project support is limited to software issues reproduced with fabricated data. Do not send taxpayer information or request advice, return preparation, tax-treatment confirmation, or lodgement.
4
+
5
+ lodgment-calendar lists the due dates the ATO publishes for the 2026–27 lodgment program
6
+ against the facts it is handed. It does not provide professional advice. It is not a
7
+ lodgement, an ATO client account, a deferral request or a determination of when any
8
+ obligation is due.
9
+
10
+ Outputs can be wrong, incomplete, stale, or unsuitable for a given set of facts. The
11
+ calendar takes entity type, lodgement history, income and liability thresholds,
12
+ taxable status and lodgement method as the caller supplies them and does not verify
13
+ them. The ATO says its program list is a guide only, can set an earlier date for a
14
+ client, and changes its pages during the year. Confirm each client's dates in Online
15
+ services for agents, the practitioner lodgment service or on the statement itself
16
+ before acting.
17
+
18
+ `UNKNOWN` rows are the result, not a gap to fill. Do not replace one with its nominal
19
+ date or a guess.
20
+
21
+ Do not publish client names, TFNs, client-identifying ABNs, lodgement records or other
22
+ sensitive personal information in issues, pull requests, examples, tests, or
23
+ repository content. Fixtures in this repository are fabricated.
24
+
25
+ See [LICENSE](LICENSE) for copyright and [SECURITY.md](SECURITY.md) for vulnerability
26
+ reporting.
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Ryan Duguid
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
@@ -0,0 +1,6 @@
1
+ include NOTICE
2
+ include CITATION.cff DISCLAIMER.md RELEASE_NOTES.md RELEASING.md SECURITY.md llms.txt uv.lock .gitignore LICENSE README.md
3
+ graft lodgmentcalendar
4
+ graft tests
5
+ graft docs
6
+ global-exclude *.py[cod]
@@ -0,0 +1,20 @@
1
+ lodgment-calendar
2
+ Copyright 2026 Ryan Duguid (https://github.com/ryanduguid)
3
+
4
+ This software is licensed under the Functional Source License,
5
+ Version 1.1, ALv2 Future License (FSL-1.1-ALv2); see LICENSE.
6
+
7
+ For each version licensed under FSL-1.1-ALv2, an additional licence under the
8
+ Apache License, Version 2.0 becomes effective on the second anniversary of the
9
+ date that version was made available.
10
+
11
+ Versions made available before this change remain available under the
12
+ licences they were released with.
13
+
14
+ Redistribution under FSL-1.1-ALv2 requires including its terms or a link to
15
+ them and keeping the copyright notices supplied with the software.
16
+ Redistribution under another applicable licence follows that licence's
17
+ conditions.
18
+
19
+ This product includes work by Ryan Duguid
20
+ (https://github.com/ryanduguid/australian-accounting/tree/main/packages/lodgment-calendar).
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: lodgment-calendar
3
+ Version: 0.1.0
4
+ Summary: ATO lodgment program due dates for BAS, IAS and income tax returns, with cited rules and UNKNOWN for missing facts. Preparation aid, not a determination.
5
+ Author: Ryan Duguid
6
+ License-Expression: FSL-1.1-ALv2
7
+ Project-URL: Homepage, https://github.com/ryanduguid/australian-accounting/tree/main/packages/lodgment-calendar
8
+ Project-URL: Repository, https://github.com/ryanduguid/australian-accounting/tree/main/packages/lodgment-calendar
9
+ Project-URL: Issues, https://github.com/ryanduguid/australian-accounting/issues
10
+ Keywords: australia,ato,lodgment-program,bas,tax-agent,bas-agent,due-dates
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
18
+ Requires-Python: >=3.14
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ License-File: NOTICE
22
+ Provides-Extra: dev
23
+ Requires-Dist: ruff==0.17.0; extra == "dev"
24
+ Requires-Dist: pyright[nodejs]==1.1.414; extra == "dev"
25
+ Requires-Dist: nodejs-wheel-binaries==24.19.0; extra == "dev"
26
+ Requires-Dist: pytest==9.1.1; extra == "dev"
27
+ Requires-Dist: coverage==7.16.2; extra == "dev"
28
+ Requires-Dist: pytest-cov==7.1.0; extra == "dev"
29
+ Requires-Dist: build==1.6.1; extra == "dev"
30
+ Requires-Dist: setuptools==84.2.1; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # Lodgment calendar
34
+
35
+ `lodgment-calendar` works out lodgement and payment due dates for BAS, IAS and income tax
36
+ returns under the ATO's 2026–27 lodgment program, for self-lodgers and for clients of
37
+ registered tax and BAS agents. Each date carries its rule, the ATO page it comes from and
38
+ the date that page was checked. A date that depends on a fact you did not supply, or that
39
+ the ATO pages leave open, comes back `UNKNOWN` with the missing condition named.
40
+
41
+ Distribution `lodgment-calendar`, import package `lodgmentcalendar`. Library only: this
42
+ component ships no command.
43
+
44
+ **Package lifecycle:** published. Install `lodgment-calendar` from PyPI with
45
+ `pip install lodgment-calendar`; see [release notes](RELEASE_NOTES.md) and
46
+ [DISCLAIMER.md](DISCLAIMER.md).
47
+
48
+ It is a preparation aid. It reads the facts you pass, contacts no service, calls no ATO
49
+ API and lodges nothing. Ryan Duguid is not a registered tax agent or BAS agent. Project
50
+ support is limited to software issues reproduced with fabricated data. Do not send
51
+ taxpayer information.
52
+
53
+ ## Example
54
+
55
+ ```python
56
+ from lodgmentcalendar import Facts, due_dates
57
+
58
+ result = due_dates(
59
+ "bas", "company", "2026-27", "bas_agent", reporting_cycle="quarterly",
60
+ facts=Facts(consolidated_head_company=False, lodges_electronically=True,
61
+ previous_statement_lodged_electronically=True,
62
+ includes_monthly_payg_obligation=False),
63
+ )
64
+ for row in result["obligations"]:
65
+ print(row["period"], row["status"], row["nominal_due_date"], row["due_date"], row["rule_id"])
66
+ ```
67
+
68
+ ```
69
+ 2026-27 Q1 DETERMINED 2026-11-25 2026-11-25 AS-Q-AGENT
70
+ 2026-27 Q2 DETERMINED 2027-02-28 2027-03-02 AS-Q-28
71
+ 2026-27 Q3 DETERMINED 2027-05-26 2027-05-26 AS-Q-AGENT
72
+ 2026-27 Q4 UNKNOWN 2027-08-25 None AS-Q-AGENT
73
+ ```
74
+
75
+ Quarter 2 is due on Sunday 28 February 2027. Monday 1 March is Labour Day in Western
76
+ Australia, which moves the date for every state, so the statement is due on 2 March.
77
+ Quarter 4 is `UNKNOWN` because the ATO marks 25 August 2027 'to be confirmed'.
78
+
79
+ ## Inputs
80
+
81
+ `due_dates(obligation, entity_type, financial_year, channel, *, reporting_cycle=None, facts=None, extra_holidays=None, holidays_complete_until=None)`
82
+
83
+ | Input | Values |
84
+ | --- | --- |
85
+ | `obligation` | `bas`, `ias` or `income_tax_return` |
86
+ | `entity_type` | `individual`, `trust`, `partnership`, `company` or `smsf` |
87
+ | `financial_year` | The year of the statement periods, or the income year a return covers, as `2026-27` |
88
+ | `channel` | `self`, `tax_agent` or `bas_agent` (a BAS agent cannot lodge an income tax return) |
89
+ | `reporting_cycle` | `monthly` or `quarterly`, for `bas` and `ias` only. A monthly `bas` reports GST monthly; other monthly activity statements are `ias`. For a consolidated head company, a quarterly `ias` is its PAYG instalment activity statement |
90
+ | `facts` | A `Facts` with the conditions below; each is `True`, `False` or `None` (not supplied) |
91
+ | `extra_holidays` | Up to 50 `date: name` holidays the ATO table does not list (see below) |
92
+ | `holidays_complete_until` | A `date` to which the ATO table and `extra_holidays` hold every holiday (see below) |
93
+
94
+ This release records statement periods in 2026-27 and income tax returns for the 2025-26
95
+ income year, which are the returns the 2026–27 program covers. Any other year returns one
96
+ `UNKNOWN` row.
97
+
98
+ The `Facts` fields are the conditions the ATO pages make the dates depend on:
99
+ `prior_returns_outstanding`, `overdue_returns_lodged_by_31_october`,
100
+ `on_agent_client_list_by_cutoff`, `large_or_medium`, `member_large_or_medium`,
101
+ `new_registrant`, `prior_year_return_taxable`, `current_year_return_taxable`,
102
+ `latest_tax_liability_20k_or_more`, `total_income_over_2m`,
103
+ `prior_year_non_taxable_or_refund`, `current_year_non_taxable_or_refund`,
104
+ `consolidated_head_company`, `first_consolidated_return`, `lodges_electronically`,
105
+ `previous_statement_lodged_electronically`, `includes_monthly_payg_obligation`,
106
+ `annual_turnover_up_to_10m` and
107
+ `deferred_gst_registered`. `FACT_MEANINGS` in `lodgmentcalendar.due_dates` gives the
108
+ ATO's wording for each. Only the facts on a date's decision path are read; a `None` on
109
+ that path makes the date `UNKNOWN`.
110
+
111
+ Invalid inputs raise `ValueError`: an unknown value, a malformed year, a cycle on an
112
+ income tax return, a BAS agent lodging an income tax return or a fact that is not
113
+ `True`, `False` or `None`.
114
+
115
+ ## Output
116
+
117
+ The result holds `obligations`, `counts` by status, `request`, `facts_used`,
118
+ `holiday_calendar`, `not_decided`, `warnings` and `source_checked`. Each obligation row has:
119
+
120
+ | Field | Meaning |
121
+ | --- | --- |
122
+ | `kind` | `lodgment`, `payment` (only where the payment date differs) or `concession` |
123
+ | `status` | `DETERMINED` or `UNKNOWN` |
124
+ | `due_date` | The date after the next-business-day roll; `null` when `UNKNOWN` |
125
+ | `nominal_due_date` | The date the rule names, before the roll, where the rule names one |
126
+ | `rule_id`, `summary` | The rule applied, in plain English |
127
+ | `source_url`, `source_provision`, `source_checked` | The ATO page, the table or heading on it, and the review date |
128
+ | `holiday_roll` | The weekend days and holidays passed over, with the holiday table's URL |
129
+ | `missing` | Each fact not supplied or question the ATO pages leave open |
130
+ | `payment` | On lodgement rows: `with_lodgment`, `separate`, `none` or `unknown` |
131
+
132
+ ## Weekends and public holidays
133
+
134
+ The holiday calendar is the ATO's own: Tables 1 and 2 of
135
+ [Lodgment and payment dates on weekends or public holidays](https://www.ato.gov.au/tax-and-super-professionals/for-tax-professionals/prepare-and-lodge/registered-agent-lodgment-program/lodgment-and-payment-dates-on-weekends-or-public-holidays),
136
+ checked on 20 October 2026 and again on 28 October 2026. Under that page, a date that
137
+ falls on a Saturday, a Sunday or a public holiday for the whole of any state or territory
138
+ moves to the next business day for taxpayers in every state. The tables cover 1 July 2026 to 30 June 2027. A later date
139
+ that is not a weekend cannot be shown to be a business day, so it is `UNKNOWN` with its
140
+ nominal date kept. A holiday missing from the tables can only move a date later.
141
+
142
+ To settle those dates, pass the missing holidays from an official source as
143
+ `extra_holidays` and the last date your list is complete to as
144
+ `holidays_complete_until`. Holidays alone never extend coverage, because a list holding
145
+ one 2027 holiday is not a list that has 2027 covered. Each one must be a weekday the ATO
146
+ table does not already list, and shows in `holiday_roll` and `holiday_calendar` marked
147
+ '(caller-supplied)'.
148
+
149
+ ```python
150
+ from datetime import date
151
+
152
+ result = due_dates("bas", "trust", "2026-27", "self", reporting_cycle="quarterly",
153
+ facts=Facts(lodges_electronically=True),
154
+ holidays_complete_until=date(2027, 8, 31))
155
+ print(result["obligations"][3]["due_date"])
156
+ ```
157
+
158
+ ```
159
+ 2027-08-11
160
+ ```
161
+
162
+ This assumes no whole-of-state holiday falls between 1 July and 31 August 2027 beyond
163
+ those you pass; the calendar takes that statement as given.
164
+
165
+ ## Scope
166
+
167
+ Modelled rules, open questions and every source are listed in the
168
+ [primary-source review](docs/primary-source-review-2026-10-20.md). The calendar does not
169
+ model substituted accounting periods, companies that are not full self-assessment
170
+ taxpayers, APRA-regulated funds, annual GST returns, instalment notices, FBT or other
171
+ obligation types. It does not check whether the facts you pass are true, apply a
172
+ client-specific date the ATO has set, or decide whether anything was lodged or paid on
173
+ time.
174
+
175
+ ## Licence
176
+
177
+ Licensed under the Functional Source License, Version 1.1, ALv2 Future License (FSL-1.1-ALv2). You may use, modify and redistribute it for any purpose except a Competing Use as defined in LICENSE (making it available to others in a competing commercial product or service), and each version becomes available under Apache-2.0 two years after it is made available. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,145 @@
1
+ # Lodgment calendar
2
+
3
+ `lodgment-calendar` works out lodgement and payment due dates for BAS, IAS and income tax
4
+ returns under the ATO's 2026–27 lodgment program, for self-lodgers and for clients of
5
+ registered tax and BAS agents. Each date carries its rule, the ATO page it comes from and
6
+ the date that page was checked. A date that depends on a fact you did not supply, or that
7
+ the ATO pages leave open, comes back `UNKNOWN` with the missing condition named.
8
+
9
+ Distribution `lodgment-calendar`, import package `lodgmentcalendar`. Library only: this
10
+ component ships no command.
11
+
12
+ **Package lifecycle:** published. Install `lodgment-calendar` from PyPI with
13
+ `pip install lodgment-calendar`; see [release notes](RELEASE_NOTES.md) and
14
+ [DISCLAIMER.md](DISCLAIMER.md).
15
+
16
+ It is a preparation aid. It reads the facts you pass, contacts no service, calls no ATO
17
+ API and lodges nothing. Ryan Duguid is not a registered tax agent or BAS agent. Project
18
+ support is limited to software issues reproduced with fabricated data. Do not send
19
+ taxpayer information.
20
+
21
+ ## Example
22
+
23
+ ```python
24
+ from lodgmentcalendar import Facts, due_dates
25
+
26
+ result = due_dates(
27
+ "bas", "company", "2026-27", "bas_agent", reporting_cycle="quarterly",
28
+ facts=Facts(consolidated_head_company=False, lodges_electronically=True,
29
+ previous_statement_lodged_electronically=True,
30
+ includes_monthly_payg_obligation=False),
31
+ )
32
+ for row in result["obligations"]:
33
+ print(row["period"], row["status"], row["nominal_due_date"], row["due_date"], row["rule_id"])
34
+ ```
35
+
36
+ ```
37
+ 2026-27 Q1 DETERMINED 2026-11-25 2026-11-25 AS-Q-AGENT
38
+ 2026-27 Q2 DETERMINED 2027-02-28 2027-03-02 AS-Q-28
39
+ 2026-27 Q3 DETERMINED 2027-05-26 2027-05-26 AS-Q-AGENT
40
+ 2026-27 Q4 UNKNOWN 2027-08-25 None AS-Q-AGENT
41
+ ```
42
+
43
+ Quarter 2 is due on Sunday 28 February 2027. Monday 1 March is Labour Day in Western
44
+ Australia, which moves the date for every state, so the statement is due on 2 March.
45
+ Quarter 4 is `UNKNOWN` because the ATO marks 25 August 2027 'to be confirmed'.
46
+
47
+ ## Inputs
48
+
49
+ `due_dates(obligation, entity_type, financial_year, channel, *, reporting_cycle=None, facts=None, extra_holidays=None, holidays_complete_until=None)`
50
+
51
+ | Input | Values |
52
+ | --- | --- |
53
+ | `obligation` | `bas`, `ias` or `income_tax_return` |
54
+ | `entity_type` | `individual`, `trust`, `partnership`, `company` or `smsf` |
55
+ | `financial_year` | The year of the statement periods, or the income year a return covers, as `2026-27` |
56
+ | `channel` | `self`, `tax_agent` or `bas_agent` (a BAS agent cannot lodge an income tax return) |
57
+ | `reporting_cycle` | `monthly` or `quarterly`, for `bas` and `ias` only. A monthly `bas` reports GST monthly; other monthly activity statements are `ias`. For a consolidated head company, a quarterly `ias` is its PAYG instalment activity statement |
58
+ | `facts` | A `Facts` with the conditions below; each is `True`, `False` or `None` (not supplied) |
59
+ | `extra_holidays` | Up to 50 `date: name` holidays the ATO table does not list (see below) |
60
+ | `holidays_complete_until` | A `date` to which the ATO table and `extra_holidays` hold every holiday (see below) |
61
+
62
+ This release records statement periods in 2026-27 and income tax returns for the 2025-26
63
+ income year, which are the returns the 2026–27 program covers. Any other year returns one
64
+ `UNKNOWN` row.
65
+
66
+ The `Facts` fields are the conditions the ATO pages make the dates depend on:
67
+ `prior_returns_outstanding`, `overdue_returns_lodged_by_31_october`,
68
+ `on_agent_client_list_by_cutoff`, `large_or_medium`, `member_large_or_medium`,
69
+ `new_registrant`, `prior_year_return_taxable`, `current_year_return_taxable`,
70
+ `latest_tax_liability_20k_or_more`, `total_income_over_2m`,
71
+ `prior_year_non_taxable_or_refund`, `current_year_non_taxable_or_refund`,
72
+ `consolidated_head_company`, `first_consolidated_return`, `lodges_electronically`,
73
+ `previous_statement_lodged_electronically`, `includes_monthly_payg_obligation`,
74
+ `annual_turnover_up_to_10m` and
75
+ `deferred_gst_registered`. `FACT_MEANINGS` in `lodgmentcalendar.due_dates` gives the
76
+ ATO's wording for each. Only the facts on a date's decision path are read; a `None` on
77
+ that path makes the date `UNKNOWN`.
78
+
79
+ Invalid inputs raise `ValueError`: an unknown value, a malformed year, a cycle on an
80
+ income tax return, a BAS agent lodging an income tax return or a fact that is not
81
+ `True`, `False` or `None`.
82
+
83
+ ## Output
84
+
85
+ The result holds `obligations`, `counts` by status, `request`, `facts_used`,
86
+ `holiday_calendar`, `not_decided`, `warnings` and `source_checked`. Each obligation row has:
87
+
88
+ | Field | Meaning |
89
+ | --- | --- |
90
+ | `kind` | `lodgment`, `payment` (only where the payment date differs) or `concession` |
91
+ | `status` | `DETERMINED` or `UNKNOWN` |
92
+ | `due_date` | The date after the next-business-day roll; `null` when `UNKNOWN` |
93
+ | `nominal_due_date` | The date the rule names, before the roll, where the rule names one |
94
+ | `rule_id`, `summary` | The rule applied, in plain English |
95
+ | `source_url`, `source_provision`, `source_checked` | The ATO page, the table or heading on it, and the review date |
96
+ | `holiday_roll` | The weekend days and holidays passed over, with the holiday table's URL |
97
+ | `missing` | Each fact not supplied or question the ATO pages leave open |
98
+ | `payment` | On lodgement rows: `with_lodgment`, `separate`, `none` or `unknown` |
99
+
100
+ ## Weekends and public holidays
101
+
102
+ The holiday calendar is the ATO's own: Tables 1 and 2 of
103
+ [Lodgment and payment dates on weekends or public holidays](https://www.ato.gov.au/tax-and-super-professionals/for-tax-professionals/prepare-and-lodge/registered-agent-lodgment-program/lodgment-and-payment-dates-on-weekends-or-public-holidays),
104
+ checked on 20 October 2026 and again on 28 October 2026. Under that page, a date that
105
+ falls on a Saturday, a Sunday or a public holiday for the whole of any state or territory
106
+ moves to the next business day for taxpayers in every state. The tables cover 1 July 2026 to 30 June 2027. A later date
107
+ that is not a weekend cannot be shown to be a business day, so it is `UNKNOWN` with its
108
+ nominal date kept. A holiday missing from the tables can only move a date later.
109
+
110
+ To settle those dates, pass the missing holidays from an official source as
111
+ `extra_holidays` and the last date your list is complete to as
112
+ `holidays_complete_until`. Holidays alone never extend coverage, because a list holding
113
+ one 2027 holiday is not a list that has 2027 covered. Each one must be a weekday the ATO
114
+ table does not already list, and shows in `holiday_roll` and `holiday_calendar` marked
115
+ '(caller-supplied)'.
116
+
117
+ ```python
118
+ from datetime import date
119
+
120
+ result = due_dates("bas", "trust", "2026-27", "self", reporting_cycle="quarterly",
121
+ facts=Facts(lodges_electronically=True),
122
+ holidays_complete_until=date(2027, 8, 31))
123
+ print(result["obligations"][3]["due_date"])
124
+ ```
125
+
126
+ ```
127
+ 2027-08-11
128
+ ```
129
+
130
+ This assumes no whole-of-state holiday falls between 1 July and 31 August 2027 beyond
131
+ those you pass; the calendar takes that statement as given.
132
+
133
+ ## Scope
134
+
135
+ Modelled rules, open questions and every source are listed in the
136
+ [primary-source review](docs/primary-source-review-2026-10-20.md). The calendar does not
137
+ model substituted accounting periods, companies that are not full self-assessment
138
+ taxpayers, APRA-regulated funds, annual GST returns, instalment notices, FBT or other
139
+ obligation types. It does not check whether the facts you pass are true, apply a
140
+ client-specific date the ATO has set, or decide whether anything was lodged or paid on
141
+ time.
142
+
143
+ ## Licence
144
+
145
+ Licensed under the Functional Source License, Version 1.1, ALv2 Future License (FSL-1.1-ALv2). You may use, modify and redistribute it for any purpose except a Competing Use as defined in LICENSE (making it available to others in a competing commercial product or service), and each version becomes available under Apache-2.0 two years after it is made available. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,19 @@
1
+ # v0.1.0
2
+
3
+ This is the first PyPI release of `lodgment-calendar`, published through
4
+ `release-lodgment-calendar.yml`, the monorepo's namespaced, attested release workflow.
5
+
6
+ - `due_dates` returns lodgement, payment and concession dates for monthly and quarterly
7
+ BAS and IAS periods in 2026-27 and for 2025-26 income tax returns of individuals,
8
+ trusts, partnerships, companies (including head companies of consolidated groups) and
9
+ SMSFs, lodged by the taxpayer or through a registered tax or BAS agent.
10
+ - Applies the 2026–27 registered agent and BAS agent lodgment program dates and
11
+ concessions, the 2-week online concession for quarterly statements and the December
12
+ BAS concession, each with its ATO source, provision and review date.
13
+ - Moves dates to the next business day using the ATO's 2026–27 public holiday tables.
14
+ Callers can add holidays the tables do not list and state the date their list is
15
+ complete to, which settles dates after 30 June 2027.
16
+ - Returns `UNKNOWN`, naming the missing condition, for any date that depends on a fact
17
+ not supplied, a date the ATO pages leave open or a day outside the holiday tables.
18
+ - Relicensed from Apache-2.0 to FSL-1.1-ALv2 (Functional Source License, with
19
+ Apache-2.0 as the future licence). Released versions keep their licence.
@@ -0,0 +1,20 @@
1
+ # Releasing
2
+
3
+ This project is a preparation aid. A release is a tagged source snapshot, not a
4
+ determination, and it does not authorise anyone to skip the current-source check below.
5
+
6
+ ## Before tagging
7
+
8
+ 1. Read every ATO page in `SOURCES` in `lodgmentcalendar/rules.py` and the holiday
9
+ page in `lodgmentcalendar/holidays.py` live. If a date, condition or table moved, update
10
+ the rule, its test, `SOURCE_CHECKED` and the primary-source review in the same commit.
11
+ 2. `uv run --locked --extra dev pytest --cov --cov-branch`
12
+ 3. `uv run --locked --extra dev ruff check .`
13
+ 4. `uv run --locked --extra dev pyright`
14
+ 5. Run the README example and compare its output with the README.
15
+
16
+ ## Version
17
+
18
+ The version source is `[project].version` in `pyproject.toml`. Keep `__version__` in
19
+ `lodgmentcalendar/_version.py` aligned with it; the package identity test checks both
20
+ copies. Update the release-note heading, citation and lockfiles in the same commit.
@@ -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, job-cost, access-token or other sensitive data.
12
+
13
+ A valid report will be acknowledged within 7 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.