]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
[ERP-219] Добавлена дополнительная проверка по истории каталога , исправленно сохране... origin/feature_filippov_ERP-219_fiw_add_sales_and_craste_checs
authorAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Thu, 12 Feb 2026 14:10:34 +0000 (17:10 +0300)
committerAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Thu, 12 Feb 2026 14:10:34 +0000 (17:10 +0300)
erp24/api2/controllers/DataController.php
erp24/migrations/m260212_120000_add_marketplace_fields_to_sales.php [new file with mode: 0644]
erp24/migrations/m260212_130000_alter_payments_pay_arr_nullable_in_sales.php [new file with mode: 0644]
erp24/records/MarketplaceOrders.php
erp24/records/Sales.php
erp24/services/MarketplaceService.php
erp24/services/UploadService.php

index a21d306963fa319575ad8e5384f36465b38e063c..b3c814250b635b39acbf80ed8d58a3ce992d0001 100644 (file)
@@ -46,6 +46,7 @@ use yii_app\records\PricesZakup;
 use yii_app\records\Products1cNomenclature;
 use yii_app\records\Products1cPropType;
 use yii_app\records\Products1c;
+use yii_app\records\Products1cClassDynamic;
 use yii_app\records\Products1cAdditionalCharacteristics;
 use yii_app\records\ReplacementInvoice;
 use yii_app\records\ReplacementInvoiceProducts;
@@ -876,22 +877,22 @@ class DataController extends BaseController
         foreach ($marketplaceOrders as $marketplaceOrder) {
             /* @var MarketplaceOrders $marketplaceOrder */
             $items = Json::decode(Json::encode($marketplaceOrder->items));
-            $itemsToComment = [];
             $itemsFiltered = [];
             $summ = 0;
-            foreach ($items as $item) {
-                $itemsToComment[] = $item['offer_id'] . ' - ' . $item['offer_name'];
-                $product1c = Products1c::find()->where(['articule' => $item['offer_id']])->one();
-                if (!empty($product1c->id)) {
-                    $itemsFiltered []= [
-                        'product_id' => $product1c->id ?? '',
-                        'color' => '',
-                        'price' => $item['price'],
-                        'quantity' => $item['count'],
-                        'seller_id' => '',
-                    ];
-                }
-                $summ += $item['price'] * $item['count'];
+
+            $productsItemsArticule = $this->getProductsItemsArticule($items);
+            $itemsToComment = $productsItemsArticule['itemsToComment'];
+
+            foreach ($productsItemsArticule['isProductWithGuid'] as $item) {
+                $itemsFiltered []= [
+                    'product_id' => $item['product_id'] ?? '',
+                    'color' => '',
+                    'price' => $item['price'],
+                    'quantity' => $item['quantity'],
+                    'seller_id' => '',
+                ];
+
+                $summ += $item['price'] * $item['quantity'];
             }
             if (!empty($itemsFiltered)) {
                 $eit = ExportImportTable::find()->where(['entity' => 'city_store', 'export_id' => 1, 'entity_id' => $marketplaceOrder->store_id])->one();
@@ -941,7 +942,7 @@ class DataController extends BaseController
 
                 $itemsWithoutSku = array_map(
                     fn(array $p) => "{$p['product_id']} x{$p['quantity']}",
-                    $marketplaceOrder->getProductsWithoutArticule()
+                    $productsItemsArticule['isProductWithoutGuid']
                 );
                 if (!empty($itemsWithoutSku)) {
                     $itemsWithoutSkuString = ', Товары без артикула: ' . implode(', ',$itemsWithoutSku);
@@ -1003,6 +1004,64 @@ class DataController extends BaseController
         return $result;
     }
 
+    /**
+     * Получение товаров с проверкой наличия артикулов в базе
+     * @param array $items Массив товаров из заказа маркетплейса
+     * @return array
+     */
+    private function getProductsItemsArticule($items): array
+    {
+        $products = $items;
+        $isProductWithGuid = [];
+        $isProductWithoutGuid = [];
+        $itemsToComment = [];
+
+        foreach ($products as $product) {
+            $itemsToComment[] = $product['offer_id'] . ' - ' . $product['offer_name'];
+
+            /** @var Products1c $productRow */
+            $productRow = Products1c::find()
+                ->where(['articule' => $product['offer_id']])
+                ->one();
+
+            if (!empty($productRow->id)) {
+                $isProductWithGuid[$product['offer_id']] = [
+                    'product_id' => $productRow->id ?? '',
+                    'color' => '',
+                    'price' => $product['price'],
+                    'quantity' => $product['count'],
+                    'seller_id' => '',
+                ];
+            } else {
+                $product1cClassDynamic = Products1cClassDynamic::find()
+                    ->where(['articule' => $product['offer_id']])
+                    ->andWhere(['active' => Products1cClassDynamic::ACTIVE])
+                    ->one();
+
+                if (!empty($product1cClassDynamic->id)) {
+                    $isProductWithGuid[$product['offer_id']] = [
+                        'product_id' => $product1cClassDynamic->id ?? '',
+                        'color' => '',
+                        'price' => $product['price'],
+                        'quantity' => $product['count'],
+                        'seller_id' => '',
+                    ];
+                } else {
+                    $isProductWithoutGuid[] = [
+                        'product_id' => $product['offer_name'] ?? null,
+                        'quantity' => $product['count'] ?? null,
+                    ];
+                }
+            }
+        }
+
+        return [
+            'isProductWithoutGuid' => $isProductWithoutGuid,
+            'isProductWithGuid' => $isProductWithGuid,
+            'itemsToComment' => $itemsToComment,
+        ];
+    }
+
 
     private function getCancelledMarketplaceOrders(): array {
         $canceledStatusId = MarketplaceOrderStatusTypes::find()
diff --git a/erp24/migrations/m260212_120000_add_marketplace_fields_to_sales.php b/erp24/migrations/m260212_120000_add_marketplace_fields_to_sales.php
new file mode 100644 (file)
index 0000000..4727b9a
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+
+use yii\db\Migration;
+
+/**
+ * Добавление полей marketplace_order_id и marketplace_name в таблицу sales
+ *
+ * Эти поля необходимы для связи чеков продаж с заказами маркетплейсов (ФлауВау, ЯндексМаркет)
+ * и решения проблемы с orphaned записями в sales_products
+ */
+class m260212_120000_add_marketplace_fields_to_sales extends Migration
+{
+    const TABLE_NAME = 'erp24.sales';
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeUp()
+    {
+        $table = $this->db->schema->getTableSchema(self::TABLE_NAME);
+        if ($table === null) {
+            return;
+        }
+
+        // Добавляем поле marketplace_order_id (GUID заказа маркетплейса)
+        if (!$this->db->schema->getTableSchema(self::TABLE_NAME, true)->getColumn('marketplace_order_id')) {
+            $this->addColumn(
+                self::TABLE_NAME,
+                'marketplace_order_id',
+                $this->string(64)->null()->comment('GUID заказа маркетплейса из таблицы marketplace_orders')
+            );
+        }
+
+        // Добавляем поле marketplace_name (название маркетплейса)
+        if (!$this->db->schema->getTableSchema(self::TABLE_NAME, true)->getColumn('marketplace_name')) {
+            $this->addColumn(
+                self::TABLE_NAME,
+                'marketplace_name',
+                $this->string(50)->null()->comment('Название маркетплейса (ФлауВау, ЯндексМаркет)')
+            );
+        }
+
+        // Добавляем индекс для быстрого поиска по marketplace_order_id
+        $this->createIndex(
+            'idx-sales-marketplace_order_id',
+            self::TABLE_NAME,
+            'marketplace_order_id'
+        );
+
+        // Добавляем составной индекс для аналитики по маркетплейсам
+        $this->createIndex(
+            'idx-sales-marketplace_name_date',
+            self::TABLE_NAME,
+            ['marketplace_name', 'date']
+        );
+
+        echo "    > Поля marketplace_order_id и marketplace_name успешно добавлены в таблицу erp24.sales\n";
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeDown()
+    {
+        // Удаляем индексы
+        $this->dropIndex('idx-sales-marketplace_name_date', self::TABLE_NAME);
+        $this->dropIndex('idx-sales-marketplace_order_id', self::TABLE_NAME);
+
+        // Удаляем поля
+        if ($this->db->schema->getTableSchema(self::TABLE_NAME, true)->getColumn('marketplace_name')) {
+            $this->dropColumn(self::TABLE_NAME, 'marketplace_name');
+        }
+
+        if ($this->db->schema->getTableSchema(self::TABLE_NAME, true)->getColumn('marketplace_order_id')) {
+            $this->dropColumn(self::TABLE_NAME, 'marketplace_order_id');
+        }
+
+        echo "    > Поля marketplace_order_id и marketplace_name удалены из таблицы erp24.sales\n";
+    }
+}
diff --git a/erp24/migrations/m260212_130000_alter_payments_pay_arr_nullable_in_sales.php b/erp24/migrations/m260212_130000_alter_payments_pay_arr_nullable_in_sales.php
new file mode 100644 (file)
index 0000000..6cd5032
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+use yii\db\Migration;
+
+/**
+ * Изменение полей payments и pay_arr в таблице sales на nullable
+ *
+ * Проблема: MarketplaceService создает чеки с пустыми payments и pay_arr,
+ * что приводит к ошибкам валидации при сохранении в Sales.
+ * Решение: разрешить NULL значения для этих полей.
+ */
+class m260212_130000_alter_payments_pay_arr_nullable_in_sales extends Migration
+{
+    const TABLE_NAME = 'erp24.sales';
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeUp()
+    {
+        $table = $this->db->schema->getTableSchema(self::TABLE_NAME);
+        if ($table === null) {
+            return;
+        }
+
+        // Изменяем payments на nullable
+        $this->alterColumn(
+            self::TABLE_NAME,
+            'payments',
+            $this->text()->null()->comment('JSON массив с информацией о платежах')
+        );
+
+        // Изменяем pay_arr на nullable
+        $this->alterColumn(
+            self::TABLE_NAME,
+            'pay_arr',
+            $this->string(15)->null()->comment('ID типов платежей, разделенные запятыми')
+        );
+
+        echo "    > Поля payments и pay_arr успешно изменены на nullable в таблице erp24.sales\n";
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeDown()
+    {
+        // Перед откатом нужно заполнить NULL значения пустыми строками
+        $this->update(self::TABLE_NAME, ['payments' => ''], ['payments' => null]);
+        $this->update(self::TABLE_NAME, ['pay_arr' => ''], ['pay_arr' => null]);
+
+        // Возвращаем NOT NULL ограничения
+        $this->alterColumn(
+            self::TABLE_NAME,
+            'payments',
+            $this->text()->notNull()->comment('JSON массив с информацией о платежах')
+        );
+
+        $this->alterColumn(
+            self::TABLE_NAME,
+            'pay_arr',
+            $this->string(15)->notNull()->comment('ID типов платежей, разделенные запятыми')
+        );
+
+        echo "    > Поля payments и pay_arr возвращены к NOT NULL в таблице erp24.sales\n";
+    }
+}
index a2062bb22d3391156d209725421c77c1c81abd53..d036315d9a19e728587e7cd092c8244fef9af2ff 100644 (file)
@@ -91,6 +91,14 @@ class MarketplaceOrders extends \yii\db\ActiveRecord
         return 'marketplace_orders';
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public static function primaryKey()
+    {
+        return ['id'];
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -245,6 +253,58 @@ class MarketplaceOrders extends \yii\db\ActiveRecord
         return $result;
     }
 
+    public function getProductsItemsArticule($items):array
+    {
+        $products = $items;
+        $isProductWithGuid = [];
+        $isProductWithoutGuid = [];
+        $itemsToComment = [];
+
+        foreach ($products as $product) {
+            $itemsToComment[] = $product['offer_id'] . ' - ' . $product['offer_name'];
+
+            /** @var Products1c $productRow */
+            $productRow = Products1c::find()
+                ->where(['articule' => $product['offer_id']])
+                ->one();
+            if (!empty($productRow->id)) {
+                $isProductWithGuid[$product['offer_id']] = [
+                    'product_id' => $productRow->id ?? '',
+                    'color' => '',
+                    'price' => $product['price'],
+                    'quantity' => $product['count'],
+                    'seller_id' => '',
+                ];
+
+            } else {
+                $product1cClassDynamic = Products1cClassDynamic::find()
+                    ->where(['articule' => $product['offer_id']])
+                    ->andWhere(['active' => Products1cClassDynamic::ACTIVE])
+                    ->one();
+                if (!empty($product1cClassDynamic->id)) {
+                    $isProductWithGuid[$product['offer_id']]= [
+                        'product_id' => $product1cClassDynamic->id ?? '',
+                        'color' => '',
+                        'price' => $product['price'],
+                        'quantity' => $product['count'],
+                        'seller_id' => '',
+                    ];
+                } else {
+                    $isProductWithoutGuid[] = [
+                        'product_id' => $product['offer_name'] ?? null,
+                        'quantity' => $product['count'] ?? null,
+                    ];
+                }
+            }
+        }
+
+        return [
+            'isProductWithoutGuid' => $isProductWithoutGuid,
+            'isProductWithGuid' => $isProductWithGuid,
+            'itemsToComment' => $itemsToComment,
+        ];
+    }
+
     public static function buildStatusesToCode(): array
     {
         $statuses = MarketplaceOrder1cStatuses::find()
index f5dfeec15ccbf857664918bf5ea0985d63a4931c..fba684a1172ad6422cf4522435006aefa66dd109 100755 (executable)
@@ -35,6 +35,8 @@ use yii\db\Expression;
  * @property string|null $delivery_date
  * @property int|null $pickup
  * @property int $update_source
+ * @property string|null $marketplace_order_id GUID заказа маркетплейса из таблицы marketplace_orders
+ * @property string|null $marketplace_name Название маркетплейса (ФлауВау, ЯндексМаркет)
  */
 class Sales extends \yii\db\ActiveRecord
 {
@@ -57,8 +59,8 @@ class Sales extends \yii\db\ActiveRecord
     public function rules()
     {
         return [
-            [['id', 'date', 'operation', 'status', 'summ', 'skidka', 'number', 'admin_id', 'seller_id', 'store_id_1c', 'payments', 'pay_arr' /*, 'terminal_id', 'kkm_id', 'held' */], 'required'],
-            [['date', 'date_up', 'order_id', 'pickup', 'terminal_id'], 'safe'],
+            [['id', 'date', 'operation', 'status', 'summ', 'skidka', 'number', 'admin_id', 'seller_id', 'store_id_1c' /*, 'terminal_id', 'kkm_id', 'held' */], 'required'],
+            [['date', 'date_up', 'order_id', 'pickup', 'terminal_id', 'payments', 'marketplace_order_id', 'marketplace_name'], 'safe'],
             [['summ', 'purchase_sum', 'skidka'], 'number'],
             [['update_source'], 'integer'],
             [['admin_id', 'store_id', 'phone', 'status_check', 'held', 'matrix'], 'integer'],
@@ -69,6 +71,8 @@ class Sales extends \yii\db\ActiveRecord
             [['number'], 'string', 'max' => 225],
             [['pay_arr'], 'string', 'max' => 15],
             [['terminal'], 'string', 'max' => 255],
+            [['marketplace_order_id'], 'string', 'max' => 64],
+            [['marketplace_name'], 'string', 'max' => 50],
             [['date', 'operation', 'store_id_1c', 'id'], 'unique', 'targetAttribute' => ['date', 'operation', 'store_id_1c', 'id']],
             [['id'], 'unique'],
         ];
@@ -103,6 +107,8 @@ class Sales extends \yii\db\ActiveRecord
             'held' => 'Held',
             'matrix' => 'Matrix',
             'date_up' => 'Date Up',
+            'marketplace_order_id' => 'Marketplace Order ID',
+            'marketplace_name' => 'Marketplace Name',
         ];
     }
 
index 8760b59d3c512583d4d48f1f0d0c7c800fd1e629..2f9bae882978a985b5dd1eb6c94a9c509d792a00 100644 (file)
@@ -3236,7 +3236,7 @@ class MarketplaceService
             }
 
             $createChecks->items = Json::encode($items);
-            $createChecks->payments = '';
+            $createChecks->payments = '[]';
             $createChecks->held = 1;
             $createChecks->kkm_id = $kkm_id;
             $createChecks->comments = '';
index b742dae0e7c2852c0bbf3c60b58c348e877b4388..fbdf9bd3e71a107edfb4c3f87e7e11b3532d00eb 100644 (file)
@@ -1248,10 +1248,18 @@ class UploadService {
                         $sales2->skidka = $arr["discount"] ?? '0';
                         $sales2->delivery_date = date('Y-m-d', strtotime($arr['delivery_date'] ?? ''));
                         $sales2->pickup = $arr['pickup'] ?? false;
+                        $sales2->marketplace_order_id = $arr["marketplace_order_id"] ?? null;
+                        $sales2->marketplace_name = $arr["marketplace_name"] ?? null;
                         $sales2->save();
                         
+                        // ✅ Проверка результата
                         if ($sales2->getErrors()) {
-                            LogService::apiErrorLog(json_encode(["error_id" => 21, "error" => $sales2->getErrors()], JSON_UNESCAPED_UNICODE));
+                            LogService::apiErrorLog([
+                                "error_id" => 21, 
+                                "error" => $sales2->getErrors(),
+                                "check_id" => $arr["id"]
+                            ]);
+                            continue;  // ← ПРОПУСТИТЬ создание товаров!
                         }
 
                         // Обновляем данные в очереди на создание чеков
@@ -2010,6 +2018,9 @@ class UploadService {
                     $pay_arr[] = 2;
                 }
             }
+        } else {
+            //Маркет плейс
+            $pay_arr[] = 4;
         }
 
         return $pay_arr;