]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
fix(TO8-48): fix readyto_1c strict comparison, add cron-based timeout check
authorAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Wed, 4 Mar 2026 07:09:54 +0000 (10:09 +0300)
committerAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Wed, 4 Mar 2026 07:09:54 +0000 (10:09 +0300)
- Fix `checkAndSetReadyTo1c()`: cast `readyto_1c` to int before strict
  comparison — PostgreSQL returns string "0", so `!== 0` always skipped
- Add `forceReadyTo1cByTimeout()`: batch-marks orders older than 15 min
  as ready for 1C export, independent of incoming FlowWow emails
- Add console action `marketplace/check-ready-to-1c` for cron (*/5)
- Add unit tests for both string and int readyto_1c values

erp24/commands/MarketplaceController.php
erp24/services/MarketplaceService.php
erp24/tests/unit/services/CheckReadyTo1cTest.php [new file with mode: 0644]

index d370164da055af19baa5dee14b2afb3cc30206dd..87ebaca914fa8d7378edaa8756f28da79feac9bd 100644 (file)
@@ -544,4 +544,17 @@ class MarketplaceController extends Controller
             return ExitCode::UNSPECIFIED_ERROR;
         }
     }
+
+    /**
+     * Принудительная отправка в 1С заказов, ожидающих delivery_to дольше 15 минут.
+     *
+     * Запуск: php yii marketplace/check-ready-to-1c
+     * Рекомендуемый крон: */5 * * * *
+     */
+    public function actionCheckReadyTo1c(): int
+    {
+        $count = MarketplaceService::forceReadyTo1cByTimeout(15);
+        $this->stdout("Помечено готовыми к отправке в 1С: {$count} заказов\n");
+        return ExitCode::OK;
+    }
 }
index f91b4a0325cd77a6fe43ed3ca37e2eb4a8fcc3cf..87e94a2b2ef746cdee4eb9197aab9287763dc000 100644 (file)
@@ -3489,9 +3489,34 @@ class MarketplaceService
 
     }
 
+    /**
+     * Принудительно помечает все заказы старше $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;
         }
 
diff --git a/erp24/tests/unit/services/CheckReadyTo1cTest.php b/erp24/tests/unit/services/CheckReadyTo1cTest.php
new file mode 100644 (file)
index 0000000..20599c5
--- /dev/null
@@ -0,0 +1,133 @@
+<?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);
+    }
+}