From: Auto-Claude Orchestrator Date: Tue, 24 Mar 2026 07:36:00 +0000 (+0000) Subject: feat(task-JIRA-ERP-33-20260324070448): Сбор данных по остаткам на день X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=a5a6f71992bd7ece28849da86a61e532b3c486dc;p=erp24_rep%2Fyii-erp24%2F.git feat(task-JIRA-ERP-33-20260324070448): Сбор данных по остаткам на день --- diff --git a/erp24/services/StockHistoryService.php b/erp24/services/StockHistoryService.php index ab0a1a85..e5c09ff1 100644 --- a/erp24/services/StockHistoryService.php +++ b/erp24/services/StockHistoryService.php @@ -278,7 +278,11 @@ class StockHistoryService } $msg = 'Failed to acquire advisory lock within ' . $this->getLockTimeoutSec() . ' seconds'; - Yii::error($msg, 'stock-history'); + try { + Yii::error($msg, 'stock-history'); + } catch (\Throwable $e) { + // Логирование не должно маскировать основную ошибку + } $this->sendTelegram("CRITICAL: Stock History ETL — $msg"); throw new \RuntimeException($msg); @@ -400,7 +404,11 @@ class StockHistoryService private function logResult(string $date, string $time, int $rowCount, DqResult $dqResult): void { $status = $dqResult->allPassed() ? 'SUCCESS' : 'DQ_FAILURES'; - Yii::info("Stock History ETL [{$date} {$time}]: {$status}, rows={$rowCount}", 'stock-history'); + try { + Yii::info("Stock History ETL [{$date} {$time}]: {$status}, rows={$rowCount}", 'stock-history'); + } catch (\Throwable $e) { + // Логирование не должно прерывать ETL + } } private function sendAlerts(DqResult $dqResult, string $date, string $time): void @@ -415,11 +423,20 @@ class StockHistoryService $messages = []; foreach ($criticals as $f) { $messages[] = "CRITICAL [{$f['code']}]: {$f['message']}"; - Yii::error("DQ {$f['code']}: {$f['message']}", 'stock-history'); } foreach ($majors as $f) { $messages[] = "MAJOR [{$f['code']}]: {$f['message']}"; - Yii::warning("DQ {$f['code']}: {$f['message']}", 'stock-history'); + } + + try { + foreach ($criticals as $f) { + Yii::error("DQ {$f['code']}: {$f['message']}", 'stock-history'); + } + foreach ($majors as $f) { + Yii::warning("DQ {$f['code']}: {$f['message']}", 'stock-history'); + } + } catch (\Throwable $e) { + // Логирование не должно прерывать ETL } $text = "Stock History DQ [{$date} {$time}]:\n" . implode("\n", $messages); diff --git a/erp24/tests/unit/services/StockHistoryServiceTest.php b/erp24/tests/unit/services/StockHistoryServiceTest.php index 19e65085..a2bfddbd 100644 --- a/erp24/tests/unit/services/StockHistoryServiceTest.php +++ b/erp24/tests/unit/services/StockHistoryServiceTest.php @@ -21,6 +21,12 @@ class StockHistoryServiceTest extends Unit /** * @return array{0: \yii\db\Connection, 1: \yii\db\Command} */ + /** No-op callback для подавления Telegram/Yii в тестах */ + private static function noopTelegramCallback(): callable + { + return static function (string $message): void {}; + } + private function createMockDbAndCommand(): array { $db = $this->createMock(\yii\db\Connection::class); @@ -65,7 +71,7 @@ class StockHistoryServiceTest extends Unit ); $command->method('execute')->willReturn(10); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->collect('08:00'); $this->assertTrue($result->isSuccess()); @@ -83,7 +89,8 @@ class StockHistoryServiceTest extends Unit $this->expectExceptionMessage('advisory lock'); // Анонимный класс с минимальными таймаутами для быстрого теста - $service = new class($db) extends StockHistoryService { + $noopCallback = self::noopTelegramCallback(); + $service = new class($db, $noopCallback) extends StockHistoryService { protected function getLockTimeoutSec(): int { return 1; } protected function getLockRetrySleepUs(): int { return 100000; } // 0.1 sec }; @@ -97,7 +104,7 @@ class StockHistoryServiceTest extends Unit $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('snapshotTime'); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->collect('invalid'); } @@ -112,7 +119,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryAll')->willReturn([]); $command->method('execute')->willReturn(0); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->collect('08:00'); $this->assertTrue($result->isSuccess()); @@ -145,7 +152,7 @@ class StockHistoryServiceTest extends Unit ]); $command->method('execute')->willReturn(1); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->collect('08:00'); $hasOnConflict = false; @@ -168,7 +175,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryScalar') ->willReturnOnConsecutiveCalls(5, 5, 0, 0, 0, 100, 95); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->runDqAssertions('2026-02-21', '08:00'); $this->assertTrue($result->allPassed()); @@ -182,7 +189,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryScalar') ->willReturnOnConsecutiveCalls(24, 20, 0, 0, 0, 100, 100); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->runDqAssertions('2026-02-21', '08:00'); $this->assertFalse($result->allPassed()); @@ -198,7 +205,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryScalar') ->willReturnOnConsecutiveCalls(5, 5, 0, 3, 0, 100, 100); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->runDqAssertions('2026-02-21', '08:00'); $majors = $result->getMajorFailures(); @@ -212,7 +219,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryScalar') ->willReturnOnConsecutiveCalls(5, 5, 0, 0, 0, 100, 50); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->runDqAssertions('2026-02-21', '08:00'); $majors = $result->getMajorFailures(); @@ -226,7 +233,7 @@ class StockHistoryServiceTest extends Unit $command->method('queryScalar') ->willReturnOnConsecutiveCalls(5, 0, 0, 0, 0, 0, 100); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $result = $service->runDqAssertions('2026-02-21', '08:00'); $this->assertFalse($result->allPassed()); @@ -254,7 +261,7 @@ class StockHistoryServiceTest extends Unit ); $command->method('execute')->willReturn(0); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->createPartition('2026-04'); $sql = implode(' ', $executedSql); @@ -270,7 +277,7 @@ class StockHistoryServiceTest extends Unit $this->expectException(\InvalidArgumentException::class); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->createPartition('invalid'); } @@ -290,7 +297,7 @@ class StockHistoryServiceTest extends Unit ); $command->method('execute')->willReturn(0); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->ensurePartitions(); $partitionSql = array_filter($executedSql, fn($s) => stripos($s, 'PARTITION OF') !== false); @@ -323,7 +330,7 @@ class StockHistoryServiceTest extends Unit ); $command->method('execute')->willReturn(0); - $service = new StockHistoryService($db); + $service = new StockHistoryService($db, self::noopTelegramCallback()); $service->dropOldPartitions(24); $this->assertCount(2, $droppedSql, 'Должны быть удалены 2 старые партиции (2023_11 и 2023_12)');