doku
All checks were successful
Deploy / deploy-staging (push) Successful in 32s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-08-21 01:04:21 +02:00
parent 70c86bd8ce
commit 95100d3a78
9 changed files with 66 additions and 37 deletions

View File

@@ -2116,11 +2116,20 @@ final class Router
: $this->currentTimestamp();
$settledValueAmount = null;
$settledValueCurrency = null;
$settledFxFetchId = null;
if ($this->isCryptoCurrencyCode($purchaseCurrency)) {
$settledValueCurrency = $this->requiredCurrency($settings['report_currency'] ?? 'EUR', 'report_currency');
$settledFxFetchId = $this->resolveMeasurementFxFetchId($projectKey, ['measured_at' => $purchasedAt], true);
if ($settledFxFetchId === null) {
throw new ApiException(
'Es konnte kein FX-Snapshot fuer die Krypto-Zahlung gespeichert werden. Der Miner wird nicht ohne historische Kursreferenz angelegt.',
422,
['currency' => $purchaseCurrency, 'purchased_at' => $purchasedAt]
);
}
$settledValueAmount = $purchaseCurrency === $settledValueCurrency
? $purchaseCost
: $this->convertMiningAssetAmount((float) $purchaseCost, $purchaseCurrency, $settledValueCurrency, $purchasedAt);
: $this->convertMiningAssetAmount((float) $purchaseCost, $purchaseCurrency, $settledValueCurrency, $purchasedAt, $settledFxFetchId);
if ($settledValueAmount === null) {
throw new ApiException(
'Der aktuelle Kurs fuer die Krypto-Zahlung konnte nicht ermittelt werden. Der Miner wird nicht ohne feste Bewertung gespeichert.',
@@ -2145,6 +2154,7 @@ final class Router
'reference_price_currency' => $referencePriceCurrency,
'settled_value_amount' => $settledValueAmount,
'settled_value_currency' => $settledValueCurrency,
'settled_fx_fetch_id' => $settledFxFetchId,
'auto_renew' => $isAutoRenew ? 1 : 0,
'note' => $this->optionalString($input['note'] ?? ($offer['note'] ?? null), 1000),
'is_active' => 1,

View File

@@ -463,6 +463,12 @@ final class AnalyticsService
$settledCryptoSpendValue = $latestCurrency !== ''
? $this->settledCryptoSpendValue($purchasedMiners, $latestCurrency, $latest)
: null;
$settledCryptoSpendCurrentAsset = $latestAsset !== ''
? $this->settledCryptoSpendValue($purchasedMiners, $latestAsset, $latest)
: null;
$earnedCurrentAsset = $settledCryptoSpendCurrentAsset !== null
? $holdingsCurrentAsset + $settledCryptoSpendCurrentAsset
: $holdingsCurrentAsset;
$earnedValue = ($totalHoldingsValue !== null || $settledCryptoSpendValue !== null)
? (float) ($totalHoldingsValue ?? 0.0) + (float) ($settledCryptoSpendValue ?? 0.0)
: null;
@@ -504,10 +510,14 @@ final class AnalyticsService
'wallet_balance_current_asset' => $this->roundOrNull($walletBalanceCurrentAssetEquivalent, 6),
'wallet_balance_current_asset_direct' => $this->roundOrNull($walletBalanceCurrentAssetDirect, 6),
'holdings_current_asset' => $this->roundOrNull($holdingsCurrentAsset, 6),
'earned_current_asset' => $this->roundOrNull($earnedCurrentAsset, 6),
'wallet_value' => $this->roundOrNull($walletValue, 8),
'wallet_snapshot_measured_at' => $useWalletSnapshot ? (string) ($latestWalletSnapshot['measured_at'] ?? '') : null,
'total_holdings_value' => $this->roundOrNull($totalHoldingsValue, 8),
'variable_holdings_value' => $this->roundOrNull($totalHoldingsValue, 8),
'settled_crypto_spend_value' => $this->roundOrNull($settledCryptoSpendValue, 8),
'fixed_crypto_spend_value' => $this->roundOrNull($settledCryptoSpendValue, 8),
'fixed_crypto_spend_current_asset' => $this->roundOrNull($settledCryptoSpendCurrentAsset, 8),
'earned_value' => $this->roundOrNull($earnedValue, 8),
'break_even_remaining_amount' => $this->roundOrNull($breakEvenRemainingAmount, 8),
'break_even_days_overall' => $this->roundOrNull($breakEvenDaysOverall, 4),
@@ -1677,7 +1687,11 @@ final class AnalyticsService
continue;
}
$converted = $this->convertAmount($amount, $currency, $targetCurrency, $fxContext);
$historicalFxContext = [
'fx_fetch_id' => $miner['settled_fx_fetch_id'] ?? null,
'measured_at' => $miner['purchased_at'] ?? null,
];
$converted = $this->convertAmount($amount, $currency, $targetCurrency, $historicalFxContext);
if ($converted === null) {
continue;
}

View File

@@ -1005,12 +1005,12 @@ final class MiningRepository
'INSERT INTO ' . $this->table('purchased_miners') . ' (
project_key, owner_sub, miner_offer_id, purchased_at, label, runtime_months,
mining_speed_value, mining_speed_unit, bonus_speed_value, bonus_speed_unit,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency, settled_fx_fetch_id,
daily_cost_amount, daily_cost_currency, auto_renew, note, is_active
) VALUES (
:project_key, :owner_sub, :miner_offer_id, :purchased_at, :label, :runtime_months,
:mining_speed_value, :mining_speed_unit, :bonus_speed_value, :bonus_speed_unit,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency, :settled_fx_fetch_id,
:daily_cost_amount, :daily_cost_currency, :auto_renew, :note, :is_active
)
RETURNING *'
@@ -1023,12 +1023,12 @@ final class MiningRepository
'INSERT INTO ' . $this->table('purchased_miners') . ' (
project_key, owner_sub, miner_offer_id, purchased_at, label, runtime_months,
mining_speed_value, mining_speed_unit, bonus_speed_value, bonus_speed_unit,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency, settled_fx_fetch_id,
daily_cost_amount, daily_cost_currency, auto_renew, note, is_active
) VALUES (
:project_key, :owner_sub, :miner_offer_id, :purchased_at, :label, :runtime_months,
:mining_speed_value, :mining_speed_unit, :bonus_speed_value, :bonus_speed_unit,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency, :settled_fx_fetch_id,
:daily_cost_amount, :daily_cost_currency, :auto_renew, :note, :is_active
)'
);
@@ -1059,6 +1059,7 @@ final class MiningRepository
'reference_price_currency' => $payload['reference_price_currency'] ?? null,
'settled_value_amount' => $payload['settled_value_amount'] ?? null,
'settled_value_currency' => $payload['settled_value_currency'] ?? null,
'settled_fx_fetch_id' => $payload['settled_fx_fetch_id'] ?? null,
'daily_cost_amount' => $payload['daily_cost_amount'] ?? $this->deriveDailyCostAmount($payload['total_cost_amount'] ?? null, $payload['runtime_months'] ?? null),
'daily_cost_currency' => $payload['daily_cost_currency'] ?? ($payload['currency'] ?? null),
'auto_renew' => $payload['auto_renew'] ?? 0,
@@ -1071,12 +1072,12 @@ final class MiningRepository
'INSERT INTO ' . $this->table('purchased_miners') . ' (
project_key, owner_sub, miner_offer_id, purchased_at, label, runtime_months,
mining_speed_value, mining_speed_unit, bonus_speed_value, bonus_speed_unit,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency, settled_fx_fetch_id,
daily_cost_amount, daily_cost_currency, auto_renew, note, is_active
) VALUES (
:project_key, :owner_sub, :miner_offer_id, :purchased_at, :label, :runtime_months,
:mining_speed_value, :mining_speed_unit, :bonus_speed_value, :bonus_speed_unit,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency, :settled_fx_fetch_id,
:daily_cost_amount, :daily_cost_currency, :auto_renew, :note, :is_active
)
RETURNING *'
@@ -1089,12 +1090,12 @@ final class MiningRepository
'INSERT INTO ' . $this->table('purchased_miners') . ' (
project_key, owner_sub, miner_offer_id, purchased_at, label, runtime_months,
mining_speed_value, mining_speed_unit, bonus_speed_value, bonus_speed_unit,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency,
total_cost_amount, currency, usd_reference_amount, reference_price_amount, reference_price_currency, settled_value_amount, settled_value_currency, settled_fx_fetch_id,
daily_cost_amount, daily_cost_currency, auto_renew, note, is_active
) VALUES (
:project_key, :owner_sub, :miner_offer_id, :purchased_at, :label, :runtime_months,
:mining_speed_value, :mining_speed_unit, :bonus_speed_value, :bonus_speed_unit,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency,
:total_cost_amount, :currency, :usd_reference_amount, :reference_price_amount, :reference_price_currency, :settled_value_amount, :settled_value_currency, :settled_fx_fetch_id,
:daily_cost_amount, :daily_cost_currency, :auto_renew, :note, :is_active
)'
);
@@ -1650,6 +1651,7 @@ final class MiningRepository
'reference_price_currency' => $payload['reference_price_currency'] ?? null,
'settled_value_amount' => $payload['settled_value_amount'] ?? null,
'settled_value_currency' => $payload['settled_value_currency'] ?? null,
'settled_fx_fetch_id' => $payload['settled_fx_fetch_id'] ?? null,
'daily_cost_amount' => $dailyCostAmount,
'daily_cost_currency' => $dailyCostCurrency,
'auto_renew' => $payload['auto_renew'] ?? 0,

View File

@@ -261,7 +261,8 @@ final class SchemaManager
}
if ($this->tableExists($this->prefix . 'purchased_miners') && (
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_amount') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency')
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_fx_fetch_id')
)) {
$this->upgradePurchasedMinerSettlementColumns();
$applied[] = 'purchased_miner_settlement_columns';
@@ -410,7 +411,8 @@ final class SchemaManager
}
if ($this->tableExists($this->prefix . 'purchased_miners') && (
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_amount') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency')
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_fx_fetch_id')
)) {
$this->upgradePurchasedMinerSettlementColumns();
$applied[] = 'purchased_miner_settlement_columns';
@@ -770,7 +772,8 @@ final class SchemaManager
}
if ($this->tableExists($this->prefix . 'purchased_miners') && (
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_amount') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency')
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_value_currency') ||
!$this->columnExists($this->prefix . 'purchased_miners', 'settled_fx_fetch_id')
)) {
$upgrades[] = 'purchased_miner_settlement_columns';
}
@@ -1529,11 +1532,13 @@ final class SchemaManager
? [
'ALTER TABLE ' . $table . ' ADD COLUMN IF NOT EXISTS settled_value_amount NUMERIC(20,8)',
'ALTER TABLE ' . $table . ' ADD COLUMN IF NOT EXISTS settled_value_currency VARCHAR(10)',
'ALTER TABLE ' . $table . ' ADD COLUMN IF NOT EXISTS settled_fx_fetch_id BIGINT',
"UPDATE " . $table . " SET settled_value_amount = CASE WHEN reference_price_amount IS NOT NULL AND NULLIF(BTRIM(reference_price_currency), '') IS NOT NULL AND UPPER(reference_price_currency) <> UPPER(currency) THEN reference_price_amount ELSE total_cost_amount * 0.07 END, settled_value_currency = CASE WHEN reference_price_amount IS NOT NULL AND NULLIF(BTRIM(reference_price_currency), '') IS NOT NULL AND UPPER(reference_price_currency) <> UPPER(currency) THEN reference_price_currency ELSE 'EUR' END WHERE UPPER(currency) IN ('ADA','ARB','BNB','BTC','DAI','DOGE','DOT','ETH','LINK','LTC','SOL','USDC','USDT','XRP') AND settled_value_amount IS NULL",
]
: [
'ALTER TABLE `' . $table . '` ADD COLUMN settled_value_amount DECIMAL(20,8) NULL',
'ALTER TABLE `' . $table . '` ADD COLUMN settled_value_currency VARCHAR(10) NULL',
'ALTER TABLE `' . $table . '` ADD COLUMN settled_fx_fetch_id BIGINT UNSIGNED NULL',
"UPDATE `" . $table . "` SET settled_value_amount = CASE WHEN reference_price_amount IS NOT NULL AND NULLIF(TRIM(reference_price_currency), '') IS NOT NULL AND UPPER(reference_price_currency) <> UPPER(currency) THEN reference_price_amount ELSE total_cost_amount * 0.07 END, settled_value_currency = CASE WHEN reference_price_amount IS NOT NULL AND NULLIF(TRIM(reference_price_currency), '') IS NOT NULL AND UPPER(reference_price_currency) <> UPPER(currency) THEN reference_price_currency ELSE 'EUR' END WHERE UPPER(currency) IN ('ADA','ARB','BNB','BTC','DAI','DOGE','DOT','ETH','LINK','LTC','SOL','USDC','USDT','XRP') AND settled_value_amount IS NULL",
];