}
+ /**
+ * Принудительно помечает все заказы старше $minutes минут как готовые к отправке в 1С.
+ * Вызывается из крон-команды marketplace/check-ready-to-1c.
+ */
+ public static function forceReadyTo1cByTimeout(int $minutes = 15): int
+ {
+ $orders = MarketplaceOrders::find()
+ ->where(['readyto_1c' => 0])
+ ->andWhere(['<', 'creation_date', date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"))])
+ ->all();
+
+ $count = 0;
+ foreach ($orders as $order) {
+ $order->readyto_1c = 1;
+ if ($order->save()) {
+ $count++;
+ Yii::warning("Заказ ID {$order->id} автоматически помечен как готовый к отправке в 1C (таймаут {$minutes} мин).");
+ } else {
+ Yii::error('Ошибка установки readyto_1c = 1 у заказа ID ' . $order->id . ': ' . json_encode($order->getErrors(), JSON_UNESCAPED_UNICODE));
+ }
+ }
+
+ return $count;
+ }
+
public static function checkAndSetReadyTo1c($order): void
{
- if ($order->readyto_1c !== 0) {
+ if ((int)$order->readyto_1c !== 0) {
return;
}
--- /dev/null
+<?php
+
+namespace tests\unit\services;
+
+use Codeception\Test\Unit;
+use yii_app\services\MarketplaceService;
+
+/**
+ * Тесты логики принудительной установки readyto_1c по таймауту.
+ *
+ * Покрывает:
+ * - MarketplaceService::checkAndSetReadyTo1c() — поведение со строковым "0" из PostgreSQL
+ * - Корректность проверки 15-минутного таймаута
+ *
+ * @group marketplace
+ */
+class CheckReadyTo1cTest extends Unit
+{
+ private function createFakeOrder(array $attrs): object
+ {
+ return new class($attrs) {
+ public $id;
+ public $readyto_1c;
+ public $creation_date;
+ public int $saveCallCount = 0;
+
+ public function __construct(array $attrs)
+ {
+ foreach ($attrs as $k => $v) {
+ $this->$k = $v;
+ }
+ }
+
+ public function save(): bool
+ {
+ $this->saveCallCount++;
+ return true;
+ }
+
+ public function getErrors(): array
+ {
+ return [];
+ }
+ };
+ }
+
+ /**
+ * Заказ старше 15 минут с readyto_1c = "0" (строка из PostgreSQL)
+ * должен быть помечен как готовый.
+ */
+ public function testCheckAndSetReadyTo1c_StringZero_OlderThan15Min_SetsReady(): void
+ {
+ $order = $this->createFakeOrder([
+ 'id' => 999,
+ 'readyto_1c' => "0",
+ 'creation_date' => date('Y-m-d H:i:s', strtotime('-20 minutes')),
+ ]);
+
+ MarketplaceService::checkAndSetReadyTo1c($order);
+
+ $this->assertEquals(1, $order->readyto_1c);
+ $this->assertEquals(1, $order->saveCallCount, 'save() должен быть вызван один раз');
+ }
+
+ /**
+ * Заказ старше 15 минут с readyto_1c = 0 (int)
+ * должен быть помечен как готовый.
+ */
+ public function testCheckAndSetReadyTo1c_IntZero_OlderThan15Min_SetsReady(): void
+ {
+ $order = $this->createFakeOrder([
+ 'id' => 998,
+ 'readyto_1c' => 0,
+ 'creation_date' => date('Y-m-d H:i:s', strtotime('-20 minutes')),
+ ]);
+
+ MarketplaceService::checkAndSetReadyTo1c($order);
+
+ $this->assertEquals(1, $order->readyto_1c);
+ $this->assertEquals(1, $order->saveCallCount);
+ }
+
+ /**
+ * Заказ моложе 15 минут — readyto_1c не должен измениться.
+ */
+ public function testCheckAndSetReadyTo1c_YoungerThan15Min_StaysZero(): void
+ {
+ $order = $this->createFakeOrder([
+ 'id' => 997,
+ 'readyto_1c' => "0",
+ 'creation_date' => date('Y-m-d H:i:s', strtotime('-5 minutes')),
+ ]);
+
+ MarketplaceService::checkAndSetReadyTo1c($order);
+
+ $this->assertEquals("0", $order->readyto_1c);
+ $this->assertEquals(0, $order->saveCallCount, 'save() не должен вызываться');
+ }
+
+ /**
+ * Заказ с readyto_1c = 1 — метод должен выйти сразу, не трогая заказ.
+ */
+ public function testCheckAndSetReadyTo1c_AlreadyReady_Skips(): void
+ {
+ $order = $this->createFakeOrder([
+ 'id' => 996,
+ 'readyto_1c' => 1,
+ 'creation_date' => date('Y-m-d H:i:s', strtotime('-60 minutes')),
+ ]);
+
+ MarketplaceService::checkAndSetReadyTo1c($order);
+
+ $this->assertEquals(1, $order->readyto_1c);
+ $this->assertEquals(0, $order->saveCallCount);
+ }
+
+ /**
+ * Заказ с readyto_1c = "1" (строка) — тоже пропускается.
+ */
+ public function testCheckAndSetReadyTo1c_StringOne_Skips(): void
+ {
+ $order = $this->createFakeOrder([
+ 'id' => 995,
+ 'readyto_1c' => "1",
+ 'creation_date' => date('Y-m-d H:i:s', strtotime('-60 minutes')),
+ ]);
+
+ MarketplaceService::checkAndSetReadyTo1c($order);
+
+ $this->assertEquals("1", $order->readyto_1c);
+ $this->assertEquals(0, $order->saveCallCount);
+ }
+}