Version 0.7.0: Kantonstarife 2026 (taxCH_AI/AR/SG/GR)
This commit is contained in:
+10
-3
@@ -7,10 +7,19 @@ folgen [Semantic Versioning](https://semver.org/lang/de/). Die Version steht in
|
||||
|
||||
## [Unveröffentlicht]
|
||||
|
||||
## [0.6.0] - 2026-10-11
|
||||
## [0.7.0] - 2026-10-12
|
||||
|
||||
### Hinzugefügt
|
||||
- `column -d Spalte ...` (und `project -d`) löscht Spalten: alle anderen bleiben in ihrer Reihenfolge. Fehler bei unbekannter Spalte oder wenn alle gelöscht würden. Dazu Abschnitt in `man/column.man`, Beispiel in `testall.cmds` und Tests.
|
||||
- Kantonstarife 2026 für `tax`: `demo/taxCH_AI2026`, `taxCH_AR2026`, `taxCH_SG2026`, `taxCH_GR2026` (Präfix `taxCH_` für die Schweiz; einfache Staatssteuer für Alleinstehende, vor Steuerfuss, Gemeinde und Kirche), erzeugt mit `tools/gen_tax_tables.rb`. Mit Tests, Beispiel in `testall.cmds` und Erklärung zum Steuerfuss im README.
|
||||
|
||||
### Behoben
|
||||
- `rdb man dashline` (und `headline`, `backup`, `dbase`, `accounting_ter`) zeigte als Überschrift eine Makrozeile (`dashline -- .PP`). Themen-Seiten ohne Beschreibung nehmen jetzt den Titel aus der `.TH`-Zeile.
|
||||
- `splittable -0` und mehr als 676 Stücke endeten mit einem Ruby-Abbruch (im zweiten Fall nach 676 geschriebenen Dateien). Jetzt eine Fehlermeldung, und es wird vorher geprüft, damit nichts halb geschrieben wird.
|
||||
|
||||
## [0.6.0] - 2026-10-11
|
||||
|
||||
### Hinzugefügt
|
||||
- Steuertabellen 2026 für `tax`: `demo/taxDE2026`, `taxAT2026`, `taxCH2026` (nur Bundessteuer), `taxLI2026` (nur Landessteuer), erzeugt mit `tools/gen_tax_tables.rb`, mit Tests.
|
||||
|
||||
### Geändert
|
||||
@@ -18,8 +27,6 @@ folgen [Semantic Versioning](https://semver.org/lang/de/). Die Version steht in
|
||||
- README und `man/row.man` erklären, warum `select` in bash/zsh/ksh einen Syntaxfehler gibt und wie man es trotzdem aufruft.
|
||||
|
||||
### Behoben
|
||||
- `rdb man dashline` (und `headline`, `backup`, `dbase`, `accounting_ter`) zeigte als Überschrift eine Makrozeile (`dashline -- .PP`). Themen-Seiten ohne Beschreibung nehmen jetzt den Titel aus der `.TH`-Zeile.
|
||||
- `splittable -0` und mehr als 676 Stücke endeten mit einem Ruby-Abbruch (im zweiten Fall nach 676 geschriebenen Dateien). Jetzt eine Fehlermeldung, und es wird vorher geprüft, damit nichts halb geschrieben wird.
|
||||
- `rdb man` zeigte `\\select` in den Man-Pages als `\elect`: ein doppelter Backslash wird jetzt zuerst geschützt.
|
||||
|
||||
## [0.5.0] - 2026-10-11
|
||||
|
||||
@@ -130,6 +130,10 @@ Alleinstehende (Grundtarif). Erzeugt mit `ruby tools/gen_tax_tables.rb`.
|
||||
| `taxAT2026` | Österreich, Einkommensteuer | § 33 EStG (0 % bis 13 539 €, dann 20/30/40/48/50/55 %) | exakt, vor Absetzbeträgen |
|
||||
| `taxCH2026` | Schweiz, **nur direkte Bundessteuer** | Art. 36 DBG, ESTV-Rundschreiben 2-215-D-2025 | Stufen exakt, das Gesetz rechnet in 100-Franken-Schritten |
|
||||
| `taxLI2026` | Liechtenstein, **nur Landessteuer** | Art. 19 SteG (LR 640.0, Fassung 01.07.2026) | exakt |
|
||||
| `taxCH_AI2026` | Kanton Appenzell I.Rh., einfache Staatssteuer | Art. 38 StG (ESTV-Kantonsblatt) | exakt |
|
||||
| `taxCH_AR2026` | Kanton Appenzell A.Rh., einfache Staatssteuer (Alleinstehendentarif) | Art. 39 StG, Beträge ab 2024 | exakt |
|
||||
| `taxCH_SG2026` | Kanton St. Gallen, einfache Staatssteuer | Art. 50 StG, Beträge ab 2026 | exakt |
|
||||
| `taxCH_GR2026` | Kanton Graubünden, einfache Kantonssteuer | Art. 39 StG, indexierte Beträge ab 2025 | exakt |
|
||||
|
||||
```
|
||||
tax 60000 < demo/taxDE2026 14233
|
||||
@@ -143,6 +147,20 @@ Kirchensteuer und Soli sind nicht enthalten. Für die Schweiz kommen Kanton und
|
||||
höher als der Bund), für Liechtenstein der Gemeindezuschlag: gesamt = Landessteuer × (1 + Zuschlag/100).
|
||||
Ehepaar- und Alleinerziehendentarife fehlen. Das ist keine Steuerberatung.
|
||||
|
||||
**Kantone (AI, AR, SG, GR):** Die Dateien tragen den Präfix `taxCH_` (Schweiz) vor dem Kantonskürzel; `taxCH2026` ist die Bundessteuer. Die Tabellen geben die *einfache Steuer* wieder. Sie wird mit dem Steuerfuss multipliziert,
|
||||
und Gemeinde und Kirche kommen dazu. Der Kanton setzt den Steuerfuss pro Jahr fest:
|
||||
|
||||
| Kanton | Steuerfuss Kanton 2026 | Quelle |
|
||||
|---|---|---|
|
||||
| AI | 96 % | Kantonsblatt AI (Grossratsbeschluss 1.12.2025) |
|
||||
| SG | 105 % | Budgetbeschluss des Kantonsrats (Websuche, nicht im Kantonsblatt) |
|
||||
| GR | 92 % | Grosser Rat, Budget 2026 (Websuche) |
|
||||
| AR | nicht ermittelt | AR rechnet in Steuereinheiten, die Zahl für 2026 habe ich nicht gefunden |
|
||||
|
||||
Beispiel AI bei 60 000: `tax 60000 < demo/taxCH_AI2026` = 3770, mal 0,96 = 3619 (Kantonssteuer, ohne Bezirk, Gemeinde und Kirche).
|
||||
Oberhalb einer Grenze gilt bei allen vier Kantonen ein fester Satz auf das *ganze* Einkommen (AI ab 200 000 mit 8 %,
|
||||
AR ab 260 800 mit 2,6 %, SG ab 264 500 mit 8,5 %, GR ab 780 440 mit 11 %); in der Tabelle ist das die letzte Zeile.
|
||||
|
||||
## Befehle
|
||||
|
||||
| Gruppe | Befehle |
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
income tax percent
|
||||
------ --- -------
|
||||
0 0.00 0
|
||||
3000 0.00 1
|
||||
6000 30.00 2
|
||||
9000 90.00 3
|
||||
12000 180.00 4
|
||||
15000 300.00 5
|
||||
18000 450.00 6
|
||||
22000 690.00 7
|
||||
26000 970.00 7.5
|
||||
30000 1270.00 8
|
||||
40000 2070.00 8.5
|
||||
74000 4960.00 9
|
||||
140000 10900.00 8.5
|
||||
200000 16000.00 8
|
||||
@@ -0,0 +1,14 @@
|
||||
income tax percent
|
||||
------ --- -------
|
||||
0 0.00 0
|
||||
8300 0.00 0.6
|
||||
9900 9.60 1
|
||||
11500 25.60 1.5
|
||||
15700 88.60 1.8
|
||||
27200 295.60 2.2
|
||||
41800 616.80 2.4
|
||||
54300 916.80 2.6
|
||||
74100 1431.60 2.7
|
||||
88700 1825.80 2.8
|
||||
125200 2847.80 2.9
|
||||
260800 6780.80 2.6
|
||||
@@ -0,0 +1,21 @@
|
||||
income tax percent
|
||||
------ --- -------
|
||||
0 0.00 0
|
||||
16895 0.00 2.5
|
||||
17985 27.25 4
|
||||
19075 70.85 5
|
||||
20165 125.35 6
|
||||
21255 190.75 6.5
|
||||
22345 261.60 7
|
||||
24525 414.20 8
|
||||
31065 937.40 8.5
|
||||
35425 1308.00 9
|
||||
39785 1700.40 9.5
|
||||
44145 2114.60 10.3
|
||||
65945 4360.00 10.6
|
||||
87745 6670.80 10.7
|
||||
109545 9003.40 11.2
|
||||
218545 21211.40 11.3
|
||||
327545 33528.40 11.4
|
||||
436545 45954.40 11.6
|
||||
780440 85848.40 11
|
||||
@@ -0,0 +1,9 @@
|
||||
income tax percent
|
||||
------ --- -------
|
||||
0 0.00 0
|
||||
11600 0.00 4
|
||||
15800 168.00 6
|
||||
33800 1248.00 8
|
||||
60300 3368.00 9.2
|
||||
98400 6873.20 9.4
|
||||
264500 22482.50 8.5
|
||||
@@ -238,6 +238,11 @@ tax 60000 < taxDE2026
|
||||
tax 60000 < taxAT2026
|
||||
tax 60000 < taxCH2026
|
||||
tax 60000 < taxLI2026
|
||||
## Swiss cantons (einfache Staatssteuer, single; still times the cantonal Steuerfuss, plus Gemeinde): AI AR SG GR
|
||||
tax 60000 < taxCH_AI2026
|
||||
tax 60000 < taxCH_AR2026
|
||||
tax 60000 < taxCH_SG2026
|
||||
tax 60000 < taxCH_GR2026
|
||||
## explode: parts list -> all subparts with counts (part, amount)
|
||||
explode 10001 2 parttable
|
||||
## chartdup: look for duplicate account numbers and short names in chart
|
||||
|
||||
+10
-1
@@ -880,7 +880,7 @@ Item Amount Cost Value Description
|
||||
## tabletom4 / tabletosed / tabletostruct were shown above
|
||||
## ===== Help and the terminal =====
|
||||
$ rdb --version
|
||||
rdb 0.6.0
|
||||
rdb 0.7.0
|
||||
$ howmany
|
||||
136
|
||||
$ whatis row
|
||||
@@ -980,6 +980,15 @@ $ tax 60000 < taxCH2026
|
||||
671
|
||||
$ tax 60000 < taxLI2026
|
||||
1396
|
||||
## Swiss cantons (einfache Staatssteuer, single; still times the cantonal Steuerfuss, plus Gemeinde): AI AR SG GR
|
||||
$ tax 60000 < taxCH_AI2026
|
||||
3770
|
||||
$ tax 60000 < taxCH_AR2026
|
||||
1065
|
||||
$ tax 60000 < taxCH_SG2026
|
||||
3344
|
||||
$ tax 60000 < taxCH_GR2026
|
||||
3748
|
||||
## explode: parts list -> all subparts with counts (part, amount)
|
||||
$ explode 10001 2 parttable
|
||||
Part Amount
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Rdb
|
||||
VERSION = '0.6.0'
|
||||
VERSION = '0.7.0'
|
||||
end
|
||||
|
||||
@@ -812,6 +812,19 @@ class TaxTablesTest < RdbCase
|
||||
assert_equal 0, tax(15_855, 'taxLI2026')
|
||||
end
|
||||
|
||||
def test_swiss_cantons_2026_einfache_staatssteuer
|
||||
assert_equal 3770, tax(60_000, 'taxCH_AI2026') # 2 070 + 8,5 % of 20 000
|
||||
assert_equal 16_000, tax(200_000, 'taxCH_AI2026')
|
||||
assert_equal 24_000, tax(300_000, 'taxCH_AI2026') # 8 % of the whole income
|
||||
assert_equal 1065, tax(60_000, 'taxCH_AR2026')
|
||||
assert_equal 3344, tax(60_000, 'taxCH_SG2026') # 1 248 + 8 % + 9,2 % pieces
|
||||
assert_equal 25_500, tax(300_000, 'taxCH_SG2026') # 8,5 % of the whole income
|
||||
assert_equal 3748, tax(60_000, 'taxCH_GR2026')
|
||||
assert_equal 0, tax(16_895, 'taxCH_GR2026')
|
||||
assert_equal 20, tax(5_000, 'taxCH_AI2026') # 1 % of 2 000
|
||||
%w[AR SG GR].each { |c| assert_equal 0, tax(5_000, "taxCH_#{c}2026") }
|
||||
end
|
||||
|
||||
# § 32a EStG: the table is a straight-line approximation of the curved zones
|
||||
def test_de_2026_follows_the_formula
|
||||
[12_348, 14_000, 17_799, 20_000, 33_333, 50_000, 69_878, 100_000, 277_825, 300_000].each do |x|
|
||||
|
||||
@@ -61,3 +61,34 @@ li_rates.each do |limit, rate|
|
||||
prev = [limit, rate]
|
||||
end
|
||||
write_table('taxLI2026', pts)
|
||||
|
||||
# --- Swiss cantons: the "einfache Staatssteuer" for single persons, before the Steuerfuss and
|
||||
# without municipal and church tax. Source: ESTV Kantonsblätter (Steuerinformationen 2026).
|
||||
# Each tariff is a list of [width, rate] pieces; above the last piece one flat rate applies to
|
||||
# the whole income (the cantons call this "für das ganze Einkommen").
|
||||
def staircase(pieces, flat_rate, expect_limit)
|
||||
acc = 0.0
|
||||
start = 0
|
||||
pts = []
|
||||
pieces.each do |width, rate|
|
||||
pts << [start, acc, rate]
|
||||
acc += width * rate / 100.0
|
||||
start += width
|
||||
end
|
||||
raise "limit #{start} != #{expect_limit}" unless start == expect_limit
|
||||
|
||||
pts << [start, start * flat_rate / 100.0, flat_rate]
|
||||
end
|
||||
|
||||
# AI: Art. 38 StG
|
||||
write_table('taxCH_AI2026', staircase([[3_000, 0], [3_000, 1], [3_000, 2], [3_000, 3], [3_000, 4], [3_000, 5], [4_000, 6],
|
||||
[4_000, 7], [4_000, 7.5], [10_000, 8], [34_000, 8.5], [66_000, 9], [60_000, 8.5]], 8, 200_000))
|
||||
# AR: Art. 39 Abs. 1 lit. b StG (Alleinstehendentarif, Beträge ab Steuerperiode 2024); multiplied by the Steuereinheiten
|
||||
write_table('taxCH_AR2026', staircase([[8_300, 0], [1_600, 0.6], [1_600, 1.0], [4_200, 1.5], [11_500, 1.8], [14_600, 2.2],
|
||||
[12_500, 2.4], [19_800, 2.6], [14_600, 2.7], [36_500, 2.8], [135_600, 2.9]], 2.6, 260_800))
|
||||
# SG: Art. 50 StG (Beträge ab Steuerperiode 2026)
|
||||
write_table('taxCH_SG2026', staircase([[11_600, 0], [4_200, 4], [18_000, 6], [26_500, 8], [38_100, 9.2], [166_100, 9.4]], 8.5, 264_500))
|
||||
# GR: Art. 39 Abs. 1 StG (indexierte Beträge ab Steuerperiode 2025)
|
||||
write_table('taxCH_GR2026', staircase([[16_895, 0], [1_090, 2.5], [1_090, 4], [1_090, 5], [1_090, 6], [1_090, 6.5], [2_180, 7],
|
||||
[6_540, 8], [4_360, 8.5], [4_360, 9], [4_360, 9.5], [21_800, 10.3], [21_800, 10.6],
|
||||
[21_800, 10.7], [109_000, 11.2], [109_000, 11.3], [109_000, 11.4], [343_895, 11.6]], 11.0, 780_440))
|
||||
|
||||
Reference in New Issue
Block a user