Add RVG calculation module and integrate cost calculations into CVmhErstgespraech entity

This commit is contained in:
2026-01-23 19:45:00 +01:00
parent cf60d2a91d
commit 42d396f460
6 changed files with 478 additions and 8 deletions

View File

@@ -0,0 +1,284 @@
// RVG-Kalkulation ab 1.6.2025 (strenge Stufen-Regel)
// Keine Interpolation innerhalb der Stufen nur Sprung bei Überschreiten der Obergrenze
define('custom:modules/rvg-calculator', [], function () {
const rvgTabellen = {
'2025': [ // [bis einschließlich, 1,0-Gebühr]
[500, 51.50], [1000, 93.00], [1500, 134.50], [2000, 176.00],
[3000, 235.50], [4000, 295.00], [5000, 354.50], [6000, 414.00],
[7000, 473.50], [8000, 533.00], [9000, 592.50], [10000, 652.00],
[13000, 707.00], [16000, 762.00], [19000, 817.00], [22000, 872.00],
[25000, 927.00], [30000, 1013.00], [35000, 1099.00], [40000, 1185.00],
[45000, 1271.00], [50000, 1357.00], [65000, 1456.50], [80000, 1556.00],
[95000, 1655.50], [110000, 1755.00], [125000, 1854.50], [140000, 1954.00],
[155000, 2053.50], [170000, 2153.00], [185000, 2252.50], [200000, 2352.00],
[230000, 2492.00], [260000, 2632.00], [290000, 2772.00], [320000, 2912.00],
[350000, 3052.00], [380000, 3192.00], [410000, 3332.00], [440000, 3472.00],
[470000, 3612.00], [500000, 3752.00], [550000, 3927.00], [600000, 4102.00],
[650000, 4277.00], [700000, 4452.00], [750000, 4627.00], [800000, 4802.00],
[850000, 4977.00], [900000, 5152.00], [950000, 5327.00], [1000000, 5502.00],
[1050000, 5677.00], [1100000, 5852.00], [1150000, 6027.00], [1200000, 6202.00],
[1250000, 6377.00], [1300000, 6552.00], [1350000, 6727.00], [1400000, 6902.00],
[1450000, 7077.00], [1500000, 7252.00], [1550000, 7427.00], [1600000, 7602.00],
[1650000, 7777.00], [1700000, 7952.00], [1750000, 8127.00], [1800000, 8302.00],
[1850000, 8477.00], [1900000, 8652.00], [1950000, 8827.00], [2000000, 9002.00]
]
};
function getWertgebuehr(streitwert, tabelleName) {
tabelleName = tabelleName || '2025';
const tabelle = rvgTabellen[tabelleName];
if (!tabelle) return 0;
streitwert = Number(streitwert);
if (isNaN(streitwert) || streitwert <= 0) return 0;
if (streitwert > 2000000) return 0; // Fehler: zu hoch
for (let i = 0; i < tabelle.length; i++) {
const [bis, gebuehr] = tabelle[i];
if (streitwert <= bis) {
return gebuehr;
}
}
return tabelle[tabelle.length - 1][1];
}
function getZuschlag(anzahl) {
const extra = Math.max(0, Math.floor(anzahl) - 1);
return Math.min(2.0, extra * 0.3); // +0,3 pro weiterer Person, max +2,0
}
// GKG Gerichtsgebühr berechnen (Gerichtskostengesetz)
function getGerichtsgebuehr(streitwert) {
if (streitwert <= 0) return 0;
let gebuehr = 40; // Basisgebühr bis 500€
if (streitwert <= 500) {
return gebuehr;
}
// Bis 2.000€: je angefangene 500€ weitere 21€
if (streitwert <= 2000) {
const schritte = Math.ceil((streitwert - 500) / 500);
gebuehr += schritte * 21;
return Math.round(gebuehr * 100) / 100; // Rundung auf Cent
}
gebuehr += Math.ceil((2000 - 500) / 500) * 21; // = 3 * 21 = 63
// Bis 10.000€: je angefangene 1.000€ weitere 22,50€
if (streitwert <= 10000) {
const schritte = Math.ceil((streitwert - 2000) / 1000);
gebuehr += schritte * 22.50;
return Math.round(gebuehr * 100) / 100;
}
gebuehr += Math.ceil((10000 - 2000) / 1000) * 22.50; // = 8 * 22.50 = 180
// Bis 25.000€: je angefangene 3.000€ weitere 30,50€
if (streitwert <= 25000) {
const schritte = Math.ceil((streitwert - 10000) / 3000);
gebuehr += schritte * 30.50;
return Math.round(gebuehr * 100) / 100;
}
gebuehr += Math.ceil((25000 - 10000) / 3000) * 30.50; // = 5 * 30.50 = 152.50
// Bis 50.000€: je angefangene 5.000€ weitere 40,50€
if (streitwert <= 50000) {
const schritte = Math.ceil((streitwert - 25000) / 5000);
gebuehr += schritte * 40.50;
return Math.round(gebuehr * 100) / 100;
}
gebuehr += Math.ceil((50000 - 25000) / 5000) * 40.50; // = 5 * 40.50 = 202.50
// Bis 200.000€: je angefangene 15.000€ weitere 140€
if (streitwert <= 200000) {
const schritte = Math.ceil((streitwert - 50000) / 15000);
gebuehr += schritte * 140;
return Math.round(gebuehr * 100) / 100;
}
gebuehr += Math.ceil((200000 - 50000) / 15000) * 140; // = 10 * 140 = 1400
// Bis 500.000€: je angefangene 30.000€ weitere 210€
if (streitwert <= 500000) {
const schritte = Math.ceil((streitwert - 200000) / 30000);
gebuehr += schritte * 210;
return Math.round(gebuehr * 100) / 100;
}
gebuehr += Math.ceil((500000 - 200000) / 30000) * 210; // = 10 * 210 = 2100
// Über 500.000€: je angefangene 50.000€ weitere 210€
const schritte = Math.ceil((streitwert - 500000) / 50000);
gebuehr += schritte * 210;
return Math.round(gebuehr * 100) / 100; // Rundung auf Cent
}
return {
kalkuliereKosten: function(streitwert, anzahlKlaeger, anzahlBeklagte, ustProzent, tabelle) {
anzahlKlaeger = anzahlKlaeger || 1;
anzahlBeklagte = anzahlBeklagte || 1;
if (typeof ustProzent === 'undefined' || ustProzent === null) {
ustProzent = 19;
}
tabelle = tabelle || '2025';
const ustSatz = ustProzent / 100;
const w = getWertgebuehr(streitwert, tabelle);
if (w === 0) {
return {
streitwert: streitwert,
wertgebuehr: 0,
aussergerichtlichNetto: 0,
aussergerichtlichBrutto: 0,
gerichtskosten1Instanz: 0,
anwaltskostenKlaeger1InstanzNetto: 0,
anwaltskostenKlaeger1InstanzBrutto: 0,
vergleichsgebuehrKlaeger1InstanzNetto: 0,
vergleichsgebuehrKlaeger1InstanzBrutto: 0,
anwaltskostenBeklagte1InstanzNetto: 0,
anwaltskostenBeklagte1InstanzBrutto: 0,
vergleichsgebuehrBeklagte1InstanzNetto: 0,
vergleichsgebuehrBeklagte1InstanzBrutto: 0,
gerichtskosten2Instanz: 0,
anwaltskostenKlaeger2InstanzNetto: 0,
anwaltskostenKlaeger2InstanzBrutto: 0,
vergleichsgebuehrKlaeger2InstanzNetto: 0,
vergleichsgebuehrKlaeger2InstanzBrutto: 0,
anwaltskostenBeklagte2InstanzNetto: 0,
anwaltskostenBeklagte2InstanzBrutto: 0,
vergleichsgebuehrBeklagte2InstanzNetto: 0,
vergleichsgebuehrBeklagte2InstanzBrutto: 0,
zwangsvollstreckungRaeumungNetto: 0,
zwangsvollstreckungRaeumungBrutto: 0,
vorzusch1InstanzNetto: 0,
vorzusch1InstanzBrutto: 0,
vergleich1InstanzGk: 0,
vergleich1InstanzAnwK: 0,
vergleich1InstanzSumme: 0,
saeumnis1InstanzGk: 0,
saeumnis1InstanzAnwK: 0,
saeumnis1InstanzSumme: 0
};
}
const zuschlagK = getZuschlag(anzahlKlaeger);
const zuschlagB = getZuschlag(anzahlBeklagte);
// Außergerichtlich (nur Klägerseite)
const ausserSatz = 1.3 + zuschlagK;
const ausserGeb = w * ausserSatz;
const ausserPausch = Math.min(20, 0.2 * ausserGeb);
const ausserNetto = ausserGeb + ausserPausch;
const ausserBrutto = ausserNetto * (1 + ustSatz);
// Gerichtskosten 1. Instanz (GKG-Tabelle, 3,0 Gebühren)
const gkEinfach = getGerichtsgebuehr(streitwert);
const gk1 = gkEinfach * 3.0;
// Anwaltskosten Kläger 1. Instanz
const inst1VerfK = w * (1.3 + zuschlagK);
const inst1TermK = w * 1.2;
const inst1PauschK = Math.min(20, 0.2 * (inst1VerfK + inst1TermK));
const inst1NettoK = inst1VerfK + inst1TermK + inst1PauschK;
const inst1BruttoK = inst1NettoK * (1 + ustSatz);
const vergl1KNetto = w * 1.0;
const vergl1KBrutto = vergl1KNetto * (1 + ustSatz);
// Anwaltskosten Beklagte 1. Instanz
const inst1VerfB = w * (1.3 + zuschlagB);
const inst1TermB = w * 1.2;
const inst1PauschB = Math.min(20, 0.2 * (inst1VerfB + inst1TermB));
const inst1NettoB = inst1VerfB + inst1TermB + inst1PauschB;
const inst1BruttoB = inst1NettoB * (1 + ustSatz);
const vergl1BNetto = w * 1.0;
const vergl1BBrutto = vergl1BNetto * (1 + ustSatz);
// Gerichtskosten 2. Instanz (GKG-Tabelle, 4,0 Gebühren)
const gk2 = gkEinfach * 4.0;
// Anwaltskosten Kläger 2. Instanz
const inst2VerfK = w * (1.6 + zuschlagK);
const inst2TermK = w * 1.2;
const inst2PauschK = Math.min(20, 0.2 * (inst2VerfK + inst2TermK));
const inst2NettoK = inst2VerfK + inst2TermK + inst2PauschK;
const inst2BruttoK = inst2NettoK * (1 + ustSatz);
const vergl2KNetto = w * 1.0;
const vergl2KBrutto = vergl2KNetto * (1 + ustSatz);
// Anwaltskosten Beklagte 2. Instanz
const inst2VerfB = w * (1.6 + zuschlagB);
const inst2TermB = w * 1.2;
const inst2PauschB = Math.min(20, 0.2 * (inst2VerfB + inst2TermB));
const inst2NettoB = inst2VerfB + inst2TermB + inst2PauschB;
const inst2BruttoB = inst2NettoB * (1 + ustSatz);
const vergl2BNetto = w * 1.0;
const vergl2BBrutto = vergl2BNetto * (1 + ustSatz);
// Zwangsvollstreckung Räumung
const zvBasis = w * 0.3;
const zvExtraK = (anzahlKlaeger - 1) * 0.3 * w;
const zvExtraB = (anzahlBeklagte - 1) * 0.3 * w;
const zvNetto = zvBasis + zvExtraK + zvExtraB;
const zvBrutto = zvNetto * (1 + ustSatz);
// Vorauszuschießende Kosten 1. Instanz (inkl. Gerichtskosten!)
const vorzusch1Netto = inst1VerfK + inst1TermK + inst1PauschK + gk1;
const vorzusch1Brutto = (inst1VerfK + inst1TermK + inst1PauschK) * (1 + ustSatz) + gk1;
// Vergleichsszenario 1. Instanz (Vergleichsgebühr + nur 1,0 Gerichtsgebühr statt 3,0)
const vergl1Gk = gkEinfach * 1.0; // nur 1,0 statt 3,0
const vergl1AnwKNetto = inst1VerfK + inst1TermK + vergl1KNetto + inst1PauschK; // Verf + Term + Vergl
const vergl1AnwKBrutto = vergl1AnwKNetto * (1 + ustSatz);
const vergl1GesamtBrutto = vergl1AnwKBrutto + vergl1Gk;
// Säumnisszenario 1. Instanz (0,5 Terminsgebühr statt 1,2)
const saeum1TermK = w * 0.5; // reduzierte Terminsgebühr
const saeum1AnwKNetto = inst1VerfK + saeum1TermK + inst1PauschK;
const saeum1AnwKBrutto = saeum1AnwKNetto * (1 + ustSatz);
const saeum1GesamtBrutto = saeum1AnwKBrutto + gk1;
return {
streitwert: streitwert,
wertgebuehr: w,
aussergerichtlichNetto: ausserNetto,
aussergerichtlichBrutto: ausserBrutto,
gerichtskosten1Instanz: gk1,
anwaltskostenKlaeger1InstanzNetto: inst1NettoK,
anwaltskostenKlaeger1InstanzBrutto: inst1BruttoK,
vergleichsgebuehrKlaeger1InstanzNetto: vergl1KNetto,
vergleichsgebuehrKlaeger1InstanzBrutto: vergl1KBrutto,
anwaltskostenBeklagte1InstanzNetto: inst1NettoB,
anwaltskostenBeklagte1InstanzBrutto: inst1BruttoB,
vergleichsgebuehrBeklagte1InstanzNetto: vergl1BNetto,
vergleichsgebuehrBeklagte1InstanzBrutto: vergl1BBrutto,
gerichtskosten2Instanz: gk2,
anwaltskostenKlaeger2InstanzNetto: inst2NettoK,
anwaltskostenKlaeger2InstanzBrutto: inst2BruttoK,
vergleichsgebuehrKlaeger2InstanzNetto: vergl2KNetto,
vergleichsgebuehrKlaeger2InstanzBrutto: vergl2KBrutto,
anwaltskostenBeklagte2InstanzNetto: inst2NettoB,
anwaltskostenBeklagte2InstanzBrutto: inst2BruttoB,
vergleichsgebuehrBeklagte2InstanzNetto: vergl2BNetto,
vergleichsgebuehrBeklagte2InstanzBrutto: vergl2BBrutto,
zwangsvollstreckungRaeumungNetto: zvNetto,
zwangsvollstreckungRaeumungBrutto: zvBrutto,
vorzusch1InstanzNetto: vorzusch1Netto,
vorzusch1InstanzBrutto: vorzusch1Brutto,
vergleich1InstanzGk: vergl1Gk,
vergleich1InstanzAnwK: vergl1AnwKBrutto,
vergleich1InstanzSumme: vergl1GesamtBrutto,
saeumnis1InstanzGk: gk1,
saeumnis1InstanzAnwK: saeum1AnwKBrutto,
saeumnis1InstanzSumme: saeum1GesamtBrutto
};
}
};
});

View File

@@ -0,0 +1,55 @@
define('custom:views/c-vmh-erstgespraech/fields/rvg-calculated', [
'views/fields/currency',
'custom:modules/rvg-calculator'
], function (Dep, RvgCalculator) {
return Dep.extend({
setup: function () {
Dep.prototype.setup.call(this);
this.calculating = false;
// Listen to changes on relevant fields (combined listener)
this.listenTo(this.model, 'change:streitwert change:anzahlVermieter change:anzahlMieter change:anzahlSonstigeVolljhrigeBewohner change:ustSatz', this.calculate.bind(this));
// Initial calculation
this.calculate();
},
calculate: function () {
if (this.calculating) return;
this.calculating = true;
var streitwert = parseFloat(this.model.get('streitwert')) || 0;
var anzahlKlaeger = parseInt(this.model.get('anzahlVermieter')) || 1;
var anzahlMieter = parseInt(this.model.get('anzahlMieter')) || 0;
var anzahlSonstige = parseInt(this.model.get('anzahlSonstigeVolljhrigeBewohner')) || 0;
var anzahlBeklagte = anzahlMieter + anzahlSonstige;
if (anzahlBeklagte < 1) anzahlBeklagte = 1;
// USt-Satz: "0" oder "19" (String) direkt als Integer
var ustSatzString = this.model.get('ustSatz') || '19';
var ustSatz = parseInt(ustSatzString);
var result = RvgCalculator.kalkuliereKosten(streitwert, anzahlKlaeger, anzahlBeklagte, ustSatz);
// Update all cost fields
this.model.set({
'aussergerichtlicheGebuehren': result.aussergerichtlichBrutto,
'gerichtskosten1Instanz': result.gerichtskosten1Instanz,
'anwaltskostenKlaeger1Instanz': result.anwaltskostenKlaeger1InstanzBrutto,
'vorzusch1Instanz': result.vorzusch1InstanzBrutto,
'vergleich1InstanzGk': result.vergleich1InstanzGk,
'vergleich1InstanzAnwK': result.vergleich1InstanzAnwK,
'vergleich1InstanzSumme': result.vergleich1InstanzSumme,
'saeumnis1InstanzGk': result.saeumnis1InstanzGk,
'saeumnis1InstanzAnwK': result.saeumnis1InstanzAnwK,
'saeumnis1InstanzSumme': result.saeumnis1InstanzSumme
});
this.calculating = false;
}
});
});

View File

@@ -59,7 +59,18 @@
"beendigungstatbestand": "Beendigungstatbestand",
"contact": "Kontakt",
"nchsterAnruf": "Nächster Anruf",
"dokumentesvmherstgespraech": "Dokumente"
"dokumentesvmherstgespraech": "Dokumente",
"ustSatz": "USt-Satz",
"aussergerichtlicheGebuehren": "Außergerichtliche Gebühren",
"gerichtskosten1Instanz": "Gerichtskosten 1. Instanz",
"anwaltskostenKlaeger1Instanz": "Anwaltskosten Kläger 1. Instanz",
"vorzusch1Instanz": "Vorauszuschießende Kosten 1. Instanz (inkl. GK)",
"vergleich1InstanzGk": "Vergleich 1. Inst.: Gerichtskosten",
"vergleich1InstanzAnwK": "Vergleich 1. Inst.: Anwaltskosten",
"vergleich1InstanzSumme": "Vergleich 1. Inst.: Summe",
"saeumnis1InstanzGk": "Säumnis 1. Inst.: Gerichtskosten",
"saeumnis1InstanzAnwK": "Säumnis 1. Inst.: Anwaltskosten",
"saeumnis1InstanzSumme": "Säumnis 1. Inst.: Summe"
},
"links": {
"calls": "Anrufe",
@@ -122,6 +133,10 @@
"OPKonto": "Mietkonto / Offene-Posten Liste",
"WiderspruchMieter": "Widerspruch des Mieter",
"SonstigeUnterlagen": "Sonstige Unterlagen"
},
"ustSatz": {
"0": "0%",
"19": "19%"
}
}
}

View File

@@ -155,17 +155,45 @@
},
{
"name": "kostenKndigungsservice"
},
{
"name": "aussergerichtlicheGebuehren"
},
{
"name": "ustSatz"
}
],
[
{
"name": "auergerichtlicheGesetzlicheGebhren"
"name": "gerichtskosten1Instanz"
},
{
"name": "gerichtskosten"
"name": "anwaltskostenKlaeger1Instanz"
},
{
"name": "anwaltskosten"
"name": "vorzusch1Instanz"
}
],
[
{
"name": "vergleich1InstanzGk"
},
{
"name": "vergleich1InstanzAnwK"
},
{
"name": "vergleich1InstanzSumme"
}
],
[
{
"name": "saeumnis1InstanzGk"
},
{
"name": "saeumnis1InstanzAnwK"
},
{
"name": "saeumnis1InstanzSumme"
}
]
],
@@ -175,8 +203,8 @@
"tabBreak": false,
"tabLabel": null,
"hidden": false,
"noteText": "Berechnen Sie die Gebühren mittels Prozesskostenrechner bspw. https:\/\/www.rvg-rechner.de\/rvg-rechner\/pkr.html",
"noteStyle": "info",
"noteText": "Die Gebühren werden automatisch nach RVG 2025 berechnet basierend auf Streitwert, Personenanzahl und USt-Satz.",
"noteStyle": "success",
"customLabel": "Gebührenberechnung"
},
{

View File

@@ -418,6 +418,94 @@
"minuteStep": 5,
"tooltip": true,
"isCustom": true
},
"ustSatz": {
"type": "enum",
"options": ["0", "19"],
"default": "19",
"required": true,
"isCustom": true
},
"aussergerichtlicheGebuehren": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"gerichtskosten1Instanz": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"anwaltskostenKlaeger1Instanz": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"vorzusch1Instanz": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"vergleich1InstanzGk": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true,
"view": "custom:views/c-vmh-erstgespraech/fields/rvg-calculated"
},
"vergleich1InstanzAnwK": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"vergleich1InstanzSumme": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"saeumnis1InstanzGk": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"saeumnis1InstanzAnwK": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
},
"saeumnis1InstanzSumme": {
"type": "currency",
"readOnly": true,
"onlyDefaultCurrency": true,
"conversionDisabled": true,
"decimal": true,
"isCustom": true
}
},
"links": {

View File

@@ -349,8 +349,8 @@ return [
0 => 'youtube.com',
1 => 'google.com'
],
'cacheTimestamp' => 1769183183,
'microtime' => 1769183183.901404,
'cacheTimestamp' => 1769193589,
'microtime' => 1769193589.363072,
'siteUrl' => 'https://crm.bitbylaw.com',
'fullTextSearchMinLength' => 4,
'appTimestamp' => 1768843902,