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

This commit is contained in:
2026-05-04 22:22:55 +02:00
parent a9fefa7779
commit 002d450deb
4 changed files with 120 additions and 11 deletions

View File

@@ -181,6 +181,11 @@ final class Router
Http::json(['data' => $this->createMeasurement($projectKey, Http::input())], 201);
}
if (preg_match('~^measurements/(\d+)$~', $resource, $matches) && $method === 'DELETE') {
$this->deleteMeasurement($projectKey, (int) $matches[1]);
Http::json(['data' => ['deleted' => true]]);
}
if ($resource === 'measurements-import' && $method === 'POST') {
$this->repository()->ensureProject($projectKey);
Http::json(['data' => $this->importMeasurements($projectKey, Http::input())], 201);
@@ -1454,6 +1459,15 @@ final class Router
];
}
private function deleteMeasurement(string $projectKey, int $measurementId): void
{
if ($measurementId <= 0) {
throw new ApiException('measurement_id ist ungueltig.', 422);
}
$this->repository()->deleteMeasurement($projectKey, $measurementId);
}
private function syncCurrencyCatalogForMeasurement(array $payload): void
{
$priceCurrency = strtoupper(trim((string) ($payload['price_currency'] ?? '')));

View File

@@ -299,6 +299,10 @@ final class OcrService
$price = null;
$currency = null;
$normalizedText = preg_replace('/[[:space:]]+/u', ' ', trim($rawText)) ?: '';
$lines = array_values(array_filter(array_map(
static fn (string $line): string => trim($line),
preg_split('/\R/u', $rawText) ?: []
), static fn (string $line): bool => $line !== ''));
if ($normalizedText === '') {
$flags[] = 'ocr_raw_text_empty';
@@ -338,17 +342,51 @@ final class OcrService
$price = round((float) str_replace(',', '.', $priceMatch[1]), 8);
}
$coinsCandidates = array_values(array_filter($decimalCandidates, static fn (array $item): bool => $item['value'] > 10 && $item['precision'] >= 4));
if ($coinsCandidates !== []) {
usort($coinsCandidates, static function (array $a, array $b): int {
return [$b['precision'], $b['value']] <=> [$a['precision'], $a['value']];
});
$coinsTotal = round((float) $coinsCandidates[0]['value'], 6);
if (count($coinsCandidates) > 1) {
$flags[] = 'coins_ambiguous';
if ($coinsTotal === null) {
foreach ($lines as $line) {
if (!preg_match('/MINING[- ]?GUTHABEN|MINING[- ]?BALANCE|GUTHABEN|BALANCE/i', $line)) {
continue;
}
if (preg_match('/(\d+[.,]\d{4,8})/', $line, $lineCoinsMatch)) {
$coinsTotal = round((float) str_replace(',', '.', $lineCoinsMatch[1]), 6);
$flags[] = 'coins_from_balance_line';
break;
}
}
}
if ($coinsTotal === null && preg_match('/(\d+[.,]\d{4,8})\s*(?:DOGE)?\s*(?:MINING[- ]?GUTHABEN|MINING[- ]?BALANCE|GUTHABEN|BALANCE)/i', $normalizedText, $coinsMatch)) {
$coinsTotal = round((float) str_replace(',', '.', $coinsMatch[1]), 6);
$flags[] = 'coins_from_balance_context';
}
if ($coinsTotal === null) {
$coinsCandidates = array_values(array_filter($decimalCandidates, static function (array $item) use ($price): bool {
if ($item['precision'] < 4) {
return false;
}
if ($item['value'] <= 0 || $item['value'] >= 1000000) {
return false;
}
if ($price !== null && abs($item['value'] - $price) < 0.0000005) {
return false;
}
return true;
}));
if ($coinsCandidates !== []) {
usort($coinsCandidates, static function (array $a, array $b): int {
return [$b['precision'], $b['value']] <=> [$a['precision'], $a['value']];
});
$coinsTotal = round((float) $coinsCandidates[0]['value'], 6);
if (count($coinsCandidates) > 1) {
$flags[] = 'coins_ambiguous';
}
} else {
$flags[] = 'coins_missing';
}
} else {
$flags[] = 'coins_missing';
}
$priceCandidates = array_values(array_filter(

View File

@@ -548,6 +548,32 @@ final class MiningRepository
return is_array($row) ? $this->normalizeRow($row) : null;
}
public function deleteMeasurement(string $projectKey, int $measurementId): void
{
if ($measurementId <= 0) {
return;
}
$deleteRates = $this->pdo->prepare(
'DELETE FROM ' . $this->table('measurement_rates') . '
WHERE measurement_id = :measurement_id AND owner_sub = :owner_sub'
);
$deleteRates->execute([
'measurement_id' => $measurementId,
'owner_sub' => $this->ownerSub,
]);
$deleteMeasurement = $this->pdo->prepare(
'DELETE FROM ' . $this->table('measurements') . '
WHERE id = :id AND project_key = :project_key AND owner_sub = :owner_sub'
);
$deleteMeasurement->execute([
'id' => $measurementId,
'project_key' => $projectKey,
'owner_sub' => $this->ownerSub,
]);
}
public function replaceMeasurementRates(int $measurementId, string $projectKey, array $rates): void
{
$delete = $this->pdo->prepare('DELETE FROM ' . $this->table('measurement_rates') . ' WHERE measurement_id = :measurement_id AND owner_sub = :owner_sub');