feat: Wärmepumpenlizenz separat freischalten
Tests / test (push) Successful in 47s

This commit is contained in:
dh
2026-09-29 05:53:15 +00:00
parent cf2ce3aff4
commit ef708564d8
4 changed files with 110 additions and 10 deletions
+17 -9
View File
@@ -65,7 +65,7 @@ class Manager extends IPSModule implements ManagerSchnittstelle
'Name' => 'Verbraucher einstufig',
],
'{A31C9274-54F7-4BD2-9804-7AF23E86C4D1}' => [
'Katalog' => 'consumer_single',
'Katalog' => 'heat_pump',
'Name' => 'Waermepumpe',
],
'{0D94913C-0F31-4C29-A685-6EB4AE58E55D}' => [
@@ -1127,19 +1127,23 @@ class Manager extends IPSModule implements ManagerSchnittstelle
private function pruefeVerbraucherlizenzen(array $ids): void
{
[$mengen, $namen] = $this->verbraucherLizenzbelegung($ids);
$lease = $this->leseLizenzLease();
$pruefmengen = Lizenzpruefung::beruecksichtigeBestandslizenzFuerWaermepumpen(
$lease,
$mengen
);
try {
Lizenzpruefung::pruefeVerbrauchermengen($this->leseLizenzLease(), $mengen);
Lizenzpruefung::pruefeVerbrauchermengen($lease, $pruefmengen);
} catch (InvalidArgumentException $fehler) {
foreach ($mengen as $kennung => $verwendet) {
$lizenziert = Lizenzpruefung::berechtigungsMenge(
$this->leseLizenzLease(),
$kennung
);
foreach ($pruefmengen as $kennung => $verwendet) {
$lizenziert = Lizenzpruefung::berechtigungsMenge($lease, $kennung);
if ($verwendet > $lizenziert) {
$name = $namen[$kennung]
?? ($kennung === 'consumer_single' ? 'Waermepumpe (Bestandslizenz)' : $kennung);
throw new InvalidArgumentException(sprintf(
'%s: %d aktiviert, aber nur %d lizenziert. Bitte Auswahl reduzieren oder Lizenz erweitern.',
$namen[$kennung],
$name,
$verwendet,
$lizenziert
), 0, $fehler);
@@ -2329,7 +2333,11 @@ class Manager extends IPSModule implements ManagerSchnittstelle
[$mengen] = $this->verbraucherLizenzbelegung(
$this->konfigurierteAktiveVerbraucherIDs()
);
Lizenzpruefung::pruefeVerbrauchermengen($lease, $mengen);
$pruefmengen = Lizenzpruefung::beruecksichtigeBestandslizenzFuerWaermepumpen(
$lease,
$mengen
);
Lizenzpruefung::pruefeVerbrauchermengen($lease, $pruefmengen);
return true;
} catch (Throwable $fehler) {
+36
View File
@@ -117,6 +117,42 @@ final class Lizenzpruefung
return $menge;
}
/**
* Rechnet freie, bestehende Einzellizenzen auf nicht separat lizenzierte Waermepumpen an.
*
* @param array<string, mixed> $lease
* @param array<string, int> $verwendeteMengen
* @return array<string, int>
*/
public static function beruecksichtigeBestandslizenzFuerWaermepumpen(
array $lease,
array $verwendeteMengen
): array {
$waermepumpen = $verwendeteMengen['heat_pump'] ?? 0;
if ($waermepumpen <= 0) {
return $verwendeteMengen;
}
$nichtSeparatLizenziert = max(
0,
$waermepumpen - self::berechtigungsMenge($lease, 'heat_pump')
);
$verbraucher = $verwendeteMengen['consumer_single'] ?? 0;
$freieBestandslizenzen = max(
0,
self::berechtigungsMenge($lease, 'consumer_single') - $verbraucher
);
$angerechnet = min($nichtSeparatLizenziert, $freieBestandslizenzen);
if ($angerechnet === 0) {
return $verwendeteMengen;
}
$verwendeteMengen['heat_pump'] = $waermepumpen - $angerechnet;
$verwendeteMengen['consumer_single'] = $verbraucher + $angerechnet;
return $verwendeteMengen;
}
/**
* @param array<string, mixed> $lease
* @param array<string, int> $verwendeteMengen
+55
View File
@@ -173,6 +173,61 @@ final class LizenzpruefungTest extends TestCase
self::assertTrue(true);
}
public function testSeparateWaermepumpenlizenzBleibtUnveraendert(): void
{
$lease = $this->lease('manager_standard');
$lease['entitlements'][] = [
'catalog_key' => 'heat_pump',
'quantity' => 1,
'status' => 'active',
];
$verwendung = ['heat_pump' => 1];
$pruefmengen = Lizenzpruefung::beruecksichtigeBestandslizenzFuerWaermepumpen(
$lease,
$verwendung
);
self::assertSame($verwendung, $pruefmengen);
Lizenzpruefung::pruefeVerbrauchermengen($lease, $pruefmengen);
}
public function testFreieBestandslizenzDecktEineWaermepumpeAb(): void
{
$lease = $this->lease('manager_standard');
$lease['entitlements'][] = [
'catalog_key' => 'consumer_single',
'quantity' => 1,
'status' => 'active',
];
$pruefmengen = Lizenzpruefung::beruecksichtigeBestandslizenzFuerWaermepumpen(
$lease,
['heat_pump' => 1]
);
self::assertSame(['heat_pump' => 0, 'consumer_single' => 1], $pruefmengen);
Lizenzpruefung::pruefeVerbrauchermengen($lease, $pruefmengen);
}
public function testBestandslizenzDarfNichtDoppeltVerwendetWerden(): void
{
$lease = $this->lease('manager_standard');
$lease['entitlements'][] = [
'catalog_key' => 'consumer_single',
'quantity' => 1,
'status' => 'active',
];
$pruefmengen = Lizenzpruefung::beruecksichtigeBestandslizenzFuerWaermepumpen(
$lease,
['consumer_single' => 1, 'heat_pump' => 1]
);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Lizenzkontingent fuer heat_pump ueberschritten');
Lizenzpruefung::pruefeVerbrauchermengen($lease, $pruefmengen);
}
public function testLizenzcodeWirdWieAufDemServerNormalisiert(): void
{
self::assertSame(
+2 -1
View File
@@ -169,12 +169,13 @@ final class ManagerModulstrukturTest extends TestCase
'Konstant und Monatlich benoetigen eine Peak-Shaving-Lizenz.',
$inhalt
);
foreach (['battery', 'buffer_storage', 'ev_charger', 'consumer_single', 'boiler_multi'] as $katalog) {
foreach (['battery', 'buffer_storage', 'ev_charger', 'consumer_single', 'heat_pump', 'boiler_multi'] as $katalog) {
self::assertStringContainsString("'Katalog' => '" . $katalog . "'", $inhalt);
}
foreach ([
'{B7C54AF4-AD7D-4FE4-B75D-203693906251}',
'{15879A4E-D0C2-4495-83DE-46E1E462591E}',
'{A31C9274-54F7-4BD2-9804-7AF23E86C4D1}',
'{0D94913C-0F31-4C29-A685-6EB4AE58E55D}',
'{32F65988-BE55-4FD6-9FFF-CF1C4C8628F8}',
'{C92D5EEF-9632-47A5-9659-4B02BF40FBE9}',