]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
ERP-453 эндпоинты для отзывов
authormarina <m.zozirova@gmail.com>
Mon, 17 Nov 2025 07:33:34 +0000 (10:33 +0300)
committermarina <m.zozirova@gmail.com>
Mon, 17 Nov 2025 07:33:34 +0000 (10:33 +0300)
erp24/api2/controllers/ClientController.php
erp24/migrations/m251114_000000_create_table_user_reviews.php [new file with mode: 0644]
erp24/records/UserReviews.php [new file with mode: 0644]

index c7f338a73b41d67459fbc019ec8523e1172388bf..af6de708fe2a65b1fc9cc14836dddf190cc96978 100644 (file)
@@ -23,6 +23,7 @@ use yii_app\records\Users;
 use yii_app\records\UsersBonus;
 use yii_app\records\UsersBonusLevels;
 use yii_app\records\UsersEvents;
+use yii_app\records\UserReviews;
 use yii_app\services\LogService;
 
 class ClientController extends BaseController
@@ -1486,4 +1487,228 @@ class ClientController extends BaseController
 
         return $this->asJson(['response' => $mess]);
     }
+
+    /**
+     * Сохранение данных опроса пользователя
+     * Принимает объект (один отзыв) или массив отзывов
+     * @return array
+     */
+    public function actionSaveSurvey()
+    {
+        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+
+        $request = Yii::$app->request->getRawBody();
+
+        try {
+            $data = Json::decode($request);
+        } catch (\Exception $ex) {
+            LogService::apiErrorLog(json_encode([
+                'error' => 'Json body invalid',
+                'exception' => $ex->getMessage()
+            ], JSON_UNESCAPED_UNICODE));
+            return $this->asJson(['error' => ['code' => 400, 'message' => 'Json body invalid']]);
+        }
+
+        if (empty($data)) {
+            return $this->asJson(['error' => ['code' => 400, 'message' => 'Empty data received']]);
+        }
+
+        // Если пришёл объект (один отзыв) - оборачиваем в массив
+        $isSingle = false;
+        if (!isset($data[0])) {
+            $data = [$data];
+            $isSingle = true;
+        }
+
+        $requiredFields = ['survey_id', 'sale_date', 'survey_date', 'receipt_number', 'store_id', 
+                          'rating_florist', 'rating_cleanliness', 'rating_assortment', 'rating_quality', 'phone'];
+        
+        $results = [];
+        $successCount = 0;
+        $errorCount = 0;
+        $existsCount = 0;
+
+        // Обрабатываем каждый отзыв
+        foreach ($data as $index => $reviewData) {
+            // Валидация обязательных полей
+            $hasError = false;
+            foreach ($requiredFields as $field) {
+                if (!isset($reviewData[$field]) || $reviewData[$field] === '') {
+                    LogService::apiErrorLog(json_encode([
+                        'error' => "$field is required",
+                        'index' => $index,
+                        'data' => $reviewData
+                    ], JSON_UNESCAPED_UNICODE));
+                    
+                    $results[] = [
+                        'index' => $index,
+                        'status' => 'error',
+                        'message' => "$field is required",
+                        'receipt_number' => $reviewData['receipt_number'] ?? null,
+                        'phone' => $reviewData['phone'] ?? null
+                    ];
+                    $errorCount++;
+                    $hasError = true;
+                    break;
+                }
+            }
+            
+            if ($hasError) {
+                continue;
+            }
+
+            // Очистка номера телефона
+            $phone = ClientHelper::phoneClear($reviewData['phone']);
+            if (!ClientHelper::phoneVerify($phone)) {
+                LogService::apiErrorLog(json_encode([
+                    'error' => 'Invalid phone number',
+                    'index' => $index,
+                    'phone' => $reviewData['phone']
+                ], JSON_UNESCAPED_UNICODE));
+                
+                $results[] = [
+                    'index' => $index,
+                    'status' => 'error',
+                    'message' => 'Invalid phone number',
+                    'receipt_number' => $reviewData['receipt_number'],
+                    'phone' => $reviewData['phone']
+                ];
+                $errorCount++;
+                continue;
+            }
+
+            // Проверка на дубликат по номеру телефона и номеру чека
+            $existingReview = UserReviews::find()
+                ->where(['phone' => $phone])
+                ->andWhere(['receipt_number' => $reviewData['receipt_number']])
+                ->one();
+
+            if ($existingReview) {
+                LogService::apiLogs(1, json_encode([
+                    'message' => 'Review already exists',
+                    'index' => $index,
+                    'phone' => $phone,
+                    'receipt_number' => $reviewData['receipt_number'],
+                    'existing_review_id' => $existingReview->id
+                ], JSON_UNESCAPED_UNICODE));
+                
+                $results[] = [
+                    'index' => $index,
+                    'status' => 'exists',
+                    'message' => 'Отзыв уже существует',
+                    'receipt_number' => $reviewData['receipt_number'],
+                    'phone' => $phone,
+                    'review_id' => $existingReview->id
+                ];
+                $existsCount++;
+                continue;
+            }
+
+            // Создание новой записи
+            $review = new UserReviews();
+            $review->survey_id = $reviewData['survey_id'];
+            $review->sale_date = $reviewData['sale_date'];
+            $review->survey_date = $reviewData['survey_date'];
+            $review->receipt_number = $reviewData['receipt_number'];
+            $review->store_id = $reviewData['store_id'];
+            $review->admin_id = $reviewData['admin_id'] ?? null;
+            $review->rating_florist = (int)$reviewData['rating_florist'];
+            $review->rating_cleanliness = (int)$reviewData['rating_cleanliness'];
+            $review->rating_assortment = (int)$reviewData['rating_assortment'];
+            $review->rating_quality = (int)$reviewData['rating_quality'];
+            $review->phone = $phone;
+
+            if (!$review->save()) {
+                LogService::apiErrorLog(json_encode([
+                    'error' => 'Failed to save review',
+                    'index' => $index,
+                    'validation_errors' => $review->getErrors(),
+                    'data' => $reviewData
+                ], JSON_UNESCAPED_UNICODE));
+                
+                $results[] = [
+                    'index' => $index,
+                    'status' => 'error',
+                    'message' => 'Ошибка при сохранении',
+                    'receipt_number' => $reviewData['receipt_number'],
+                    'phone' => $phone,
+                    'details' => $review->getErrors()
+                ];
+                $errorCount++;
+                continue;
+            }
+
+            LogService::apiLogs(1, json_encode([
+                'message' => 'Review saved successfully',
+                'index' => $index,
+                'review_id' => $review->id,
+                'phone' => $phone
+            ], JSON_UNESCAPED_UNICODE));
+
+            $results[] = [
+                'index' => $index,
+                'status' => 'success',
+                'message' => 'Отзыв успешно сохранен',
+                'receipt_number' => $reviewData['receipt_number'],
+                'phone' => $phone,
+                'review_id' => $review->id
+            ];
+            $successCount++;
+        }
+
+        LogService::apiLogs(1, json_encode([
+            'message' => 'Processing completed',
+            'is_single' => $isSingle,
+            'total' => count($data),
+            'success' => $successCount,
+            'exists' => $existsCount,
+            'errors' => $errorCount
+        ], JSON_UNESCAPED_UNICODE));
+
+        // Если был один отзыв - возвращаем его результат напрямую
+        if ($isSingle) {
+            $result = $results[0];
+            
+            if ($result['status'] === 'success') {
+                return $this->asJson([
+                    'response' => [
+                        'code' => 200,
+                        'status' => 'success',
+                        'message' => $result['message'],
+                        'review_id' => $result['review_id']
+                    ]
+                ]);
+            } elseif ($result['status'] === 'exists') {
+                return $this->asJson([
+                    'response' => [
+                        'code' => 200,
+                        'status' => 'exists',
+                        'message' => $result['message'],
+                        'review_id' => $result['review_id']
+                    ]
+                ]);
+            } else {
+                return $this->asJson([
+                    'error' => [
+                        'code' => 400,
+                        'message' => $result['message'],
+                        'details' => $result['details'] ?? null
+                    ]
+                ]);
+            }
+        }
+
+        // Если массив - возвращаем детальную статистику
+        return $this->asJson([
+            'response' => [
+                'code' => 200,
+                'message' => 'Обработка завершена',
+                'total' => count($data),
+                'success' => $successCount,
+                'exists' => $existsCount,
+                'errors' => $errorCount,
+                'results' => $results
+            ]
+        ]);
+    }
 }
diff --git a/erp24/migrations/m251114_000000_create_table_user_reviews.php b/erp24/migrations/m251114_000000_create_table_user_reviews.php
new file mode 100644 (file)
index 0000000..dd5c789
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+use yii\db\Migration;
+
+/**
+ * Class m251114_000000_create_table_user_reviews
+ */
+class m251114_000000_create_table_user_reviews extends Migration
+{
+    const TABLE_NAME = 'erp24.user_reviews';
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeUp()
+    {
+        $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+        if (!isset($tableSchema)) {
+            $this->createTable(self::TABLE_NAME, [
+                'id' => $this->primaryKey(),
+                'survey_id' => $this->string()->notNull()->comment('ID опроса'),
+                'sale_date' => $this->timestamp()->notNull()->comment('Дата продажи'),
+                'survey_date' => $this->timestamp()->notNull()->comment('Дата опроса'),
+                'receipt_number' => $this->string()->notNull()->comment('Номер чека'),
+                'store_id' => $this->string()->notNull()->comment('ID магазина'),
+                'admin_id' => $this->string()->null()->comment('ID администратора'),
+                'rating_florist' => $this->integer()->notNull()->comment('Оценка работы флориста'),
+                'rating_cleanliness' => $this->integer()->notNull()->comment('Оценка чистоты и комфорта в магазине'),
+                'rating_assortment' => $this->integer()->notNull()->comment('Оценка ассортимента цветов'),
+                'rating_quality' => $this->integer()->notNull()->comment('Оценка выбора и качества букетов'),
+                'phone' => $this->string()->notNull()->comment('Номер телефона клиента'),
+                'created_at' => $this->timestamp()->defaultExpression('CURRENT_TIMESTAMP')->comment('Дата создания записи'),
+                'updated_at' => $this->timestamp()->defaultExpression('CURRENT_TIMESTAMP')->comment('Дата обновления записи'),
+            ]);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeDown()
+    {
+        $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+
+        if (isset($tableSchema)) {
+            $this->dropTable(self::TABLE_NAME);
+        }
+    }
+}
+
diff --git a/erp24/records/UserReviews.php b/erp24/records/UserReviews.php
new file mode 100644 (file)
index 0000000..fe02b73
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+
+/**
+ * This is the model class for table "user_reviews".
+ *
+ * @property int $id
+ * @property string $survey_id ID опроса
+ * @property string $sale_date Дата продажи
+ * @property string $survey_date Дата опроса
+ * @property string $receipt_number Номер чека
+ * @property string $store_id ID магазина
+ * @property string|null $admin_id ID администратора
+ * @property int $rating_florist Оценка работы флориста
+ * @property int $rating_cleanliness Оценка чистоты и комфорта в магазине
+ * @property int $rating_assortment Оценка ассортимента цветов
+ * @property int $rating_quality Оценка выбора и качества букетов
+ * @property string $phone Номер телефона клиента
+ * @property string $created_at Дата создания записи
+ * @property string $updated_at Дата обновления записи
+ */
+class UserReviews extends \yii\db\ActiveRecord
+{
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return 'user_reviews';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['survey_id', 'sale_date', 'survey_date', 'receipt_number', 'store_id', 'rating_florist', 'rating_cleanliness', 'rating_assortment', 'rating_quality', 'phone'], 'required'],
+            [['sale_date', 'survey_date', 'created_at', 'updated_at'], 'safe'],
+            [['rating_florist', 'rating_cleanliness', 'rating_assortment', 'rating_quality'], 'integer'],
+            [['rating_florist', 'rating_cleanliness', 'rating_assortment', 'rating_quality'], 'integer', 'min' => 1, 'max' => 5],
+            [['survey_id', 'receipt_number', 'store_id', 'admin_id', 'phone'], 'string', 'max' => 255],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'id' => 'ID',
+            'survey_id' => 'ID опроса',
+            'sale_date' => 'Дата продажи',
+            'survey_date' => 'Дата опроса',
+            'receipt_number' => 'Номер чека',
+            'store_id' => 'ID магазина',
+            'admin_id' => 'ID администратора',
+            'rating_florist' => 'Оценка работы флориста',
+            'rating_cleanliness' => 'Оценка чистоты и комфорта в магазине',
+            'rating_assortment' => 'Оценка ассортимента цветов',
+            'rating_quality' => 'Оценка выбора и качества букетов',
+            'phone' => 'Номер телефона клиента',
+            'created_at' => 'Дата создания записи',
+            'updated_at' => 'Дата обновления записи',
+        ];
+    }
+}
+