Kaynağa Gözat

命令行-修复拉取微唯宝商品逻辑

sunxbiao 6 ay önce
ebeveyn
işleme
5beb627b5f

+ 126 - 438
app/command/WiwibaoProductSync.php

@@ -4,16 +4,15 @@ declare (strict_types=1);
4 4
 namespace app\command;
5 5
 
6 6
 use app\common\enum\CommonEnum;
7
-use app\common\enum\douhuomall\DouhuomallEnum;
8 7
 use app\common\enum\store\ProductEnum;
8
+use app\common\repositories\douhuomall\DouhuomallChangeLogRepository;
9 9
 use app\common\repositories\store\product\ProductRepository;
10
+use app\entity\data\douhuomall\DouhuomallChangeLogEntity;
10 11
 use app\traits\GongApiRequest;
11 12
 use think\console\Command;
12 13
 use think\console\Input;
13 14
 use think\console\Output;
14
-use think\db\exception\DataNotFoundException;
15 15
 use think\db\exception\DbException;
16
-use think\db\exception\ModelNotFoundException;
17 16
 use think\facade\Db;
18 17
 use think\facade\Log;
19 18
 
@@ -64,15 +63,13 @@ class WiwibaoProductSync extends Command
64 63
 
65 64
             // 2. 获取本地所有SPU ID
66 65
             $douhuomallDataMap = [];
67
-            $localSpuIds = [];
68 66
             $douhuomallDataList = Db::name('douhuomall')
69 67
                 ->select()
70 68
                 ->toArray();
71 69
             if (!empty($douhuomallDataList)) {
72 70
                 $douhuomallDataMap = array_column($douhuomallDataList, null, 'spu_id');
73
-                $localSpuIds = array_keys($douhuomallDataMap);
74
-            }
75 71
 
72
+            }
76 73
             $syncedSpuIds = [];
77 74
 
78 75
             // 3. 批量处理商品数据
@@ -89,7 +86,7 @@ class WiwibaoProductSync extends Command
89 86
             }
90 87
 
91 88
             // 4. 处理需要下架的商品(本地有但第三方已下架)
92
-            $this->handleOfflineProducts($localSpuIds, $syncedSpuIds);
89
+            $this->handleOfflineProducts($syncedSpuIds, $douhuomallDataMap);
93 90
 
94 91
             return 'success';
95 92
 
@@ -142,53 +139,15 @@ class WiwibaoProductSync extends Command
142 139
             return null;
143 140
         }
144 141
 
145
-        // 2. 处理图片信息
146
-        $imageData = $this->processProductImages($goodsId, $goodsInfo);
147
-
148
-        // 3. 处理SKU信息
149
-        $skuInfo = $this->processSkuInfo($goodsInfo['sku_list'] ?? [], $goodsId);
150
-
151
-        // 4. 构建保存数据
152
-        $saveData = $this->buildSaveData($goodsInfo, $skuInfo, $imageData);
153
-
154
-        // 5. 保存到本地(使用原有的add方法逻辑)
155
-        $spuId = $this->addToDouhuomall($saveData, $douhuomallData);
156
-
157
-        // 6. 检查并处理已上架商品的价格变动
158
-        $this->checkAndProcessOnlineProduct($spuId, $saveData);
159
-
160
-        return $spuId;
161
-    }
162
-
163
-    /**
164
-     * 处理商品图片信息
165
-     */
166
-    protected function processProductImages($goodsId, $goodsInfo)
167
-    {
168
-        // 如果你需要保存图片到本地,可以在这里实现
169
-        // 否则直接返回URL
170
-        return [
171
-            'cover_url' => $goodsInfo['main_img'] ?? '',
172
-            'detail_images' => $goodsInfo['detail_img'] ?? [],
173
-            'detail_img_list' => $goodsInfo['detail_img'] ?? [] // 为了兼容以前写的代码,建议保留这个数据项,之前用的是detail_img_list字段,但我感觉他们意义一样
174
-        ];
175
-    }
176
-
177
-    /**
178
-     * 处理SKU信息
179
-     */
180
-    protected function processSkuInfo($skuList, $goodsId)
181
-    {
182
-        if (empty($skuList)) {
183
-            return [];
142
+        // 2. 处理SKU信息
143
+        if (empty($goodsInfo['sku_list'])) {
144
+            return null;
184 145
         }
185
-
186
-        $processedSkus = [];
187
-        foreach ($skuList as $sku) {
146
+        $skuInfo = [];
147
+        foreach ($goodsInfo['sku_list'] as $sku) {
188 148
             if (empty($sku['plat_price'])) {
189 149
                 continue;
190 150
             }
191
-
192 151
             $processedSku = [
193 152
                 'sku_id' => $sku['sku_id'] ?? 0,
194 153
                 'plat_price' => $sku['plat_price'],
@@ -202,22 +161,20 @@ class WiwibaoProductSync extends Command
202 161
                 'main_img' => $sku['main_img'] ?? '',
203 162
                 'attribute_json' => !empty($sku['attr']) ? $sku['attr'] : [['val' => '默认', 'name' => '默认']]
204 163
             ];
205
-
206
-            $processedSkus[] = array_merge($sku, $processedSku);
164
+            $skuInfo[] = array_merge($sku, $processedSku);
207 165
         }
208 166
 
209
-        return $processedSkus;
210
-    }
167
+        // 4. 构建保存数据
168
+        $imageData = [
169
+            'cover_url' => $goodsInfo['main_img'] ?? '',
170
+            'detail_images' => $goodsInfo['detail_img'] ?? [],
171
+            'detail_img_list' => $goodsInfo['detail_img'] ?? [] // 为了兼容以前写的代码,建议保留这个数据项,之前用的是detail_img_list字段,但我感觉他们意义一样
172
+        ];
211 173
 
212
-    /**
213
-     * 构建保存数据
214
-     */
215
-    protected function buildSaveData($goodsInfo, $skuInfo, $imageData)
216
-    {
217 174
         // 构建详情HTML
218 175
         $detailHtml = $this->buildDetailHtml($imageData['detail_images']);
219 176
 
220
-        return [
177
+        $saveData = [
221 178
             'spu_id' => $goodsInfo['goods_id'],
222 179
             'skuId_info' => $skuInfo,
223 180
             'sys_id' => '112',
@@ -234,14 +191,24 @@ class WiwibaoProductSync extends Command
234 191
             'status' => $goodsInfo['status'] ?? 0,
235 192
             'cate_ids' => $goodsInfo['cate_ids'] ?? '',
236 193
             'title' => $goodsInfo['spu_name'] ?? '',
237
-            'cxb_cate_id' => 0
194
+            'cxb_cate_id' => 0,
195
+            'third_update_time' => $goodsInfo['update_time'] ?? ''
238 196
         ];
197
+
198
+        // 5. 保存到本地(使用原有的add方法逻辑)
199
+        try {
200
+            $spuId = $this->addToDouhuomall($saveData, $douhuomallData);
201
+        } catch (DbException $e) {
202
+            return 0;
203
+        }
204
+
205
+        return $spuId;
239 206
     }
240 207
 
241 208
     /**
242 209
      * 构建详情HTML
243 210
      */
244
-    protected function buildDetailHtml($detailImages)
211
+    protected function buildDetailHtml($detailImages): string
245 212
     {
246 213
         if (empty($detailImages)) {
247 214
             return '';
@@ -299,34 +266,70 @@ class WiwibaoProductSync extends Command
299 266
                     'profit' => $data['profit'],
300 267
                     'mer_profit' => $data['mer_profit'],
301 268
                     'pension' => $data['pension'],
302
-                    'cxb_cate_id' => $data['cxb_cate_id']
269
+                    'cxb_cate_id' => $data['cxb_cate_id'],
270
+                    'third_update_time' => $data['third_update_time']
303 271
                 ];
304 272
                 Db::name('douhuomall')->insert($insertData);
273
+
274
+                // 创建完商品后立马上架
275
+                $this->insert_product($data['spu_id'], $this->config['mer_id']);
276
+
305 277
             } else {
306 278
                 // 更新
307
-                //  无意义 // 检查是否需要恢复已删除商品的上架状态
308
-                // $shouldRestore = $this->shouldRestoreProduct($findData, $data);
309
-                // if ($shouldRestore) {
310
-                //     $this->restoreProduct($data['spu_id']);
311
-                // }
312
-                $updateData = [
313
-                    'status' => $data['status'],
314
-                    'update_time' => $now,
315
-                    'cost_price' => $data['cost_price'],
316
-                    'market_price' => $data['market_price'],
317
-                    'ot_price' => $data['ot_price'],
318
-                    'mer_profit' => $data['mer_profit'],
319
-                    'pension' => $data['pension'],
320
-                    'profit' => $data['profit'],
321
-                    'skuId_info' => json_encode($data['skuId_info'], JSON_UNESCAPED_UNICODE),
322
-                    'spuId_info' => json_encode($data['spuId_info'], JSON_UNESCAPED_UNICODE),
323
-                    'title' => $data['title'],
324
-                    'cate_ids' => $data['cate_ids'],
325
-                    'cxb_cate_id' => $data['cxb_cate_id']
326
-                ];
327
-                Db::name('douhuomall')
328
-                    ->where('spu_id', $findData['spu_id'])
329
-                    ->update($updateData);
279
+                if (empty($findData['third_update_time']) || strtotime($data['third_update_time']) > strtotime($findData['third_update_time'])) {
280
+                    $updateData = [
281
+                        'status' => $data['status'],
282
+                        'update_time' => $now,
283
+                        'cost_price' => $data['cost_price'],
284
+                        'market_price' => $data['market_price'],
285
+                        'ot_price' => $data['ot_price'],
286
+                        'mer_profit' => $data['mer_profit'],
287
+                        'pension' => $data['pension'],
288
+                        'profit' => $data['profit'],
289
+                        'skuId_info' => json_encode($data['skuId_info'], JSON_UNESCAPED_UNICODE),
290
+                        'spuId_info' => json_encode($data['spuId_info'], JSON_UNESCAPED_UNICODE),
291
+                        'title' => $data['title'],
292
+                        'cate_ids' => $data['cate_ids'],
293
+                        'cxb_cate_id' => $data['cxb_cate_id'],
294
+                        'third_update_time' => $data['third_update_time']
295
+                    ];
296
+                    Db::name('douhuomall')
297
+                        ->where('spu_id', $findData['spu_id'])
298
+                        ->update($updateData);
299
+
300
+                    $productList = Db::name('store_product')
301
+                        ->where('spu_id', $findData['spu_id'])
302
+                        ->where('is_show', ProductEnum::IS_SHOW['Yes']['code'])
303
+                        ->where('is_del', ProductEnum::IS_DEL['No']['code'])
304
+                        ->where('status', '!=', ProductEnum::STATUS['Withdrawn']['code'])
305
+                        ->select()
306
+                        ->toArray();
307
+                    $productIdList = array_column($productList, 'product_id');
308
+
309
+                    // 将绑定的商品进行下架
310
+                    Db::name('store_product')
311
+                        ->whereIn('product_id', $productIdList)
312
+                        ->update([
313
+                            'is_show' => ProductEnum::IS_SHOW['No']['code'],
314
+                            'is_del' => ProductEnum::IS_DEL['Yes']['code'],
315
+                            'status' => ProductEnum::STATUS['Withdrawn']['code'],
316
+                            'is_status' => ProductEnum::IS_STATUS['Automatic']['code']
317
+                        ]);
318
+
319
+                    /** @var DouhuomallChangeLogEntity $douhuomallChangeLogEntity */
320
+                    $douhuomallChangeLogEntity = DouhuomallChangeLogEntity::newInstance();
321
+                    $douhuomallChangeLogEntity->setSpuId($findData['spu_id'])
322
+                        ->setDataJson($findData)
323
+                        ->setEffectProductJson($productIdList)
324
+                        ->setCreateTime(date('Y-m-d H:i:s'));
325
+                    /** @var DouhuomallChangeLogRepository $douhuomallChangeLogRepository */
326
+                    $douhuomallChangeLogRepository = app()->make(DouhuomallChangeLogRepository::class);
327
+                    $douhuomallChangeLogRepository->createByEntity($douhuomallChangeLogEntity);
328
+
329
+                    // 将商品重新上架
330
+                    // 创建完商品后立马上架
331
+                    $this->insert_product($data['spu_id'], $this->config['mer_id']);
332
+                }
330 333
             }
331 334
 
332 335
             return $data['spu_id'];
@@ -338,33 +341,6 @@ class WiwibaoProductSync extends Command
338 341
     }
339 342
 
340 343
     /**
341
-     * 检查是否需要恢复已删除商品的上架状态
342
-     */
343
-    protected function shouldRestoreProduct($findData, $newData)
344
-    {
345
-        // 原有逻辑:如果货物属于已被删除状态,并且新更新进来的状态非删除状态
346
-        // 并且成本价、零售价、市场价、利润率没有变动的话
347
-        if ($findData['status'] == DouhuomallEnum::STATUS['Delete']['code']
348
-            && $newData['status'] !== DouhuomallEnum::STATUS['Delete']['code']
349
-            && $newData['cost_price'] == $findData['cost_price']
350
-            && $newData['ot_price'] == $findData['ot_price']
351
-            && $newData['market_price'] == $findData['market_price']
352
-            && $newData['profit'] == $findData['profit']) {
353
-
354
-            // 检查是否有已下架的商品
355
-            $count = Db::name('store_product')
356
-                ->where('spu_id', $newData['spu_id'])
357
-                ->where('is_show', ProductEnum::IS_SHOW['No']['code'])
358
-                ->where('is_status', ProductEnum::IS_STATUS['Automatic']['code'])
359
-                ->count();
360
-
361
-            return $count > 0;
362
-        }
363
-
364
-        return false;
365
-    }
366
-
367
-    /**
368 344
      * 恢复商品上架状态
369 345
      */
370 346
     protected function restoreProduct($spuId)
@@ -380,352 +356,64 @@ class WiwibaoProductSync extends Command
380 356
     }
381 357
 
382 358
     /**
383
-     * 检查并处理已上架商品
359
+     * 处理需要下架的商品(第三方已下架)
384 360
      */
385
-    protected function checkAndProcessOnlineProduct($spuId, $syncData)
361
+    protected function handleOfflineProducts($syncedSpuIds, $douhuomallDataMap)
386 362
     {
387
-        // 检查商品是否已上架
388
-        try {
389
-            $productList = Db::name('store_product')
390
-                // ->where('is_show', ProductEnum::IS_SHOW['Yes']['code'])
391
-                ->where('spu_id', $spuId)
392
-                ->select()
393
-                ->toArray();
394
-
395
-            if (empty($productList)) {
396
-                // 如果没有该商品则自动上架
397
-                $this->insert_product($spuId, $this->config['mer_id']);
398
-                return;
399
-            }
400
-
401
-            // 解析同步数据中的价格
402
-            $syncPrices = [];
403
-            foreach ($syncData['skuId_info'] as $sku) {
404
-                $syncPrices[] = [
405
-                    'sku_id' => $sku['sku_id'] ?? '',
406
-                    'market_price' => $sku['market_price'] ?? 0,
407
-                    'cost_price' => $sku['cost_price'] ?? 0,
408
-                    'retail_price' => $sku['retail_price'] ?? 0
409
-                ];
410
-            }
411
-
412
-            foreach ($productList as $product) {
413
-
414
-                if ($product['is_show'] == ProductEnum::IS_SHOW['No']['code'] && $product['is_status'] == ProductEnum::IS_STATUS['Triggered']['code']) {
415
-                    // 如果商品 属于未上架商品(或是被员工下架了) 则不做任何处理
416
-                    continue;
417
-                }
418
-
419
-                // 获取本地商品价格信息
420
-                // 获取SKU价格
421
-                $skus = Db::name('store_product_attr_value')
422
-                    ->where('product_id', $product['product_id'])
423
-                    ->field('gong_sku_id, sku, price, cost')
424
-                    ->select()
425
-                    ->toArray();
426
-                $localPrices = [
427
-                    'product_price' => $product['price'] ?? 0,
428
-                    'product_cost' => $product['cost'] ?? 0,
429
-                    'product_ot_price' => $product['ot_price'] ?? 0,
430
-                    'skus' => $skus
431
-                ];
432
-
433
-                // 比较价格,判断是否需要下架
434
-                $priceChanged = $this->checkPriceChange($localPrices, $syncPrices);
435
-
436
-                if ($priceChanged['result'] ?? false) {
437
-                    // 价格变动超过阈值,下架商品并记录
438
-                    // $this->offlineProductWithRecord($product, $syncData, $localPrices, $syncPrices);
439
-
440
-                    $changeSkuAttrDataList = [];
441
-                    foreach ($skus as $sku) {
442
-                        $edit_price = bcadd(
443
-                            $sku['price'],
444
-                            (string)$priceChanged['sku_difference_map'][$sku['gong_sku_id']] ?? ($priceChanged['spu_difference'] ?? '0.00'),
445
-                            2
446
-                        );
447
-                        Log::info('商品价格变动:' . json_encode([
448
-                                'product_id' => $product['product_id'],
449
-                                'sku_id' => $sku['gong_sku_id'],
450
-                                'before_price' => $sku['price'],
451
-                                'edit_price' => $edit_price
452
-                            ])
453
-                        );
454
-                        $changeSkuAttrDataList[] = [
455
-                            'sku_id' => $sku['gong_sku_id'],
456
-                            'edit_price' => $edit_price
457
-                        ];
458
-                    }
459
-                    // 新规则 根据价格变动 增减商品售价
460
-                    /** @var ProductRepository $productRepository */
461
-                    $productRepository = app()->make(ProductRepository::class);
462
-                    $productRepository->editPrice($product['product_id'], $changeSkuAttrDataList);
463
-
464
-                    // 如果是系统下架的商品 则对商品重新上架
465
-                    if ($product['is_show'] == ProductEnum::IS_SHOW['No']['code'] && $product['is_status'] == ProductEnum::IS_STATUS['Automatic']['code']) {
466
-                        $this->restoreProduct($product['spu_id']);
467
-                    }
468
-                } else {
469
-                    // 价格未变动或变动很小,只更新图片
470
-                    $this->updateProductImages($spuId);
471
-                }
472
-            }
473
-        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
474
-
475
-        }
476
-    }
363
+        $localSpuIds = array_keys($douhuomallDataMap);
364
+        $offlineSpuIds = array_diff($localSpuIds, $syncedSpuIds);
477 365
 
478
-    /**
479
-     * 检查价格是否变动超过阈值
480
-     */
481
-    protected function checkPriceChange($localPrices, $syncPrices)
482
-    {
483
-        $res = [
484
-            'result' => false,
485
-            'spu_difference' => 0.00,
486
-            'sku_difference_map' => []
487
-        ];
488
-        // 如果成本价不变 则没有必要更新商品信息
489
-        // 如果没有SKU,比较商品主价格
490
-        if (empty($localPrices['skus'])) {
491
-            $localPrice = $localPrices['product_cost'];
492
-            $syncPrice = $syncPrices[0]['cost_price'] ?? 0;
493
-
494
-            if ($localPrice > 0 && $syncPrice > 0) {
495
-                $changeRate = abs(($syncPrice - $localPrice) / $localPrice);
496
-                $res['result'] = $changeRate > $this->config['price_change_rate'];
497
-                $res['spu_difference'] = bcsub((string)$syncPrice, $localPrice, 2);
498
-            }
499
-            return $res;
366
+        if (empty($offlineSpuIds)) {
367
+            return;
500 368
         }
501 369
 
502
-        // 如果有SKU,匹配SKU进行比较
503
-        foreach ($localPrices['skus'] as $localSku) {
504
-            foreach ($syncPrices as $syncSku) {
505
-                // 尝试匹配SKU
506
-                if ($this->matchSku($localSku, $syncSku)) {
507
-                    $localPrice = $localSku['cost'] ?? 0;
508
-                    $syncPrice = $syncSku['cost_price'] ?? 0;
509
-
510
-                    if ($localPrice > 0 && $syncPrice > 0) {
511
-                        $changeRate = abs(($syncPrice - $localPrice) / $localPrice);
512
-                        $res['result'] = $changeRate > $this->config['price_change_rate'];
513
-                        $res['sku_difference_map'][$localSku['gong_sku_id']] = bcsub((string)$syncPrice, $localPrice, 2);
514
-                    }
515
-                }
516
-            }
370
+        $productList = Db::name('store_product')
371
+            ->whereIn('spu_id', $offlineSpuIds)
372
+            ->where('is_show', ProductEnum::IS_SHOW['Yes']['code'])
373
+            ->where('is_del', ProductEnum::IS_DEL['No']['code'])
374
+            ->where('status', '!=', ProductEnum::STATUS['Withdrawn']['code'])
375
+            ->field('product_id, spu_id, is_show, is_del, status')
376
+            ->select()
377
+            ->toArray();
378
+        if (empty($productList)) {
379
+            return;
517 380
         }
518
-
519
-        return $res;
520
-    }
521
-
522
-    /**
523
-     * 匹配SKU(根据业务逻辑实现)
524
-     */
525
-    protected function matchSku($localSku, $syncSku)
526
-    {
527
-        // 根据SKU ID匹配
528
-        if (!empty($localSku['gong_sku_id']) && !empty($syncSku['sku_id'])) {
529
-            return $localSku['gong_sku_id'] == $syncSku['sku_id'];
381
+        $productIdList = [];
382
+        $spuIdMap = [];
383
+        foreach ($productList as $item) {
384
+            $productIdList[] = $item['product_id'];
385
+            $spuIdMap[$item['spu_id']][] = $item['product_id'];
530 386
         }
531 387
 
532
-        // 可以根据其他属性匹配,如规格等
533
-        return false;
534
-    }
535
-
536
-    /**
537
-     * 下架商品并记录变动
538
-     */
539
-    protected function offlineProductWithRecord($product, $syncData, $localPrices, $syncPrices)
540
-    {
541
-        $productId = $product['product_id'];
542
-        $spuId = $product['spu_id'];
543
-
544
-        // 1. 收集变动前数据
545
-        $beforeData = [
546
-            'product_id' => $productId,
547
-            'spu_id' => $spuId,
548
-            'title' => $product['store_name'] ?? '',
549
-            'status' => $product['is_show'] ?? 0,
550
-            'price_info' => $localPrices,
551
-            'images' => [
552
-                'image' => $product['image'] ?? '',
553
-                'slider_image' => $product['slider_image'] ?? ''
554
-            ],
555
-            'record_time' => date('Y-m-d H:i:s')
556
-        ];
557
-
558
-        // 2. 下架商品
388
+        // 将绑定的商品进行下架
559 389
         Db::name('store_product')
560
-            ->where('product_id', $productId)
390
+            ->whereIn('product_id', $productIdList)
561 391
             ->update([
562 392
                 'is_show' => ProductEnum::IS_SHOW['No']['code'],
393
+                'is_del' => ProductEnum::IS_DEL['Yes']['code'],
563 394
                 'status' => ProductEnum::STATUS['Withdrawn']['code'],
564 395
                 'is_status' => ProductEnum::IS_STATUS['Automatic']['code']
565 396
             ]);
566
-
567
-        // 3. 收集变动后数据
568
-        $afterData = [
569
-            'spu_id' => $spuId,
570
-            'sync_price_info' => $syncPrices,
571
-            'sync_title' => $syncData['title'],
572
-            'sync_status' => $syncData['status'],
573
-            'sync_time' => date('Y-m-d H:i:s')
574
-        ];
575
-
576
-        // 4. 记录变动日志
577
-        $this->recordChangeLog(
578
-            $productId,
579
-            $spuId,
580
-            'price_change',
581
-            '第三方平台价格变动超过阈值',
582
-            $beforeData,
583
-            $afterData
584
-        );
585
-
586
-        Log::info("商品下架: product_id={$productId}, spu_id={$spuId}, 原因: 价格变动");
587
-    }
588
-
589
-    /**
590
-     * 更新商品图片(基于原有updata_product_img方法)
591
-     */
592
-    protected function updateProductImages($spuId)
593
-    {
594
-        // 1. 验证该SPU是否已上架
595
-        $productId = Db::name('store_product')
596
-            ->where('spu_id', $spuId)
597
-            ->value('product_id');
598
-
599
-        if (!$productId) {
600
-            return true;
601
-        }
602
-
603
-        // 2. 查找微唯宝商品
604
-        $data = Db::name('douhuomall')
605
-            ->where('spu_id', $spuId)
606
-            ->find();
607
-
608
-        if (!$data) {
609
-            return false;
610
-        }
611
-
612
-        // 3. 解析商品信息
613
-        $spuIdInfo = json_decode($data['spuId_info'], true);
614
-
615
-        // 4. 处理图片数据
616
-        $sliderImage = $spuIdInfo['detail_img_list'] ?: '[]';
617
-        $image = $spuIdInfo['cover_url'] ?? '';
618
-
619
-        if (is_string($sliderImage)) {
620
-            $sliderImage = implode(',', json_decode($sliderImage, true));
621
-        } else if (is_array($sliderImage)) {
622
-            $sliderImage = implode(',', $sliderImage);
623
-        } else {
624
-            $sliderImage = $image;
625
-        }
626
-
627
-        // 5. 更新产品图片数据
628
-        $updateData = [
629
-            'image' => $image,
630
-            'slider_image' => $sliderImage,
631
-        ];
632
-
633
-        Db::name('store_product')
634
-            ->where('product_id', $productId)
635
-            ->update($updateData);
636
-
637
-        // 6. 更新商品详情
638
-        $detail = $spuIdInfo['detail'] ?? '';
639
-        if (!is_null(json_decode($detail))) {
640
-            $detailList = json_decode($detail);
641
-            $newDetail = '';
642
-            foreach ($detailList as $value) {
643
-                $newDetail .= "<img src='{$value}' referrerpolicy='no-referrer' /></img>";
644
-            }
645
-            $detail = $newDetail;
397
+        foreach ($spuIdMap as $spuId => $productIdListGroupBySpuId) {
398
+            /** @var DouhuomallChangeLogEntity $douhuomallChangeLogEntity */
399
+            $douhuomallChangeLogEntity = DouhuomallChangeLogEntity::newInstance();
400
+            $douhuomallChangeLogEntity->setSpuId($spuId)
401
+                ->setDataJson($douhuomallDataMap[$spuId])
402
+                ->setEffectProductJson($productIdListGroupBySpuId)
403
+                ->setCreateTime(date('Y-m-d H:i:s'));
404
+            /** @var DouhuomallChangeLogRepository $douhuomallChangeLogRepository */
405
+            $douhuomallChangeLogRepository = app()->make(DouhuomallChangeLogRepository::class);
406
+            $douhuomallChangeLogRepository->createByEntity($douhuomallChangeLogEntity);
646 407
         }
647 408
 
648
-        Db::name('store_product_content')
649
-            ->where('product_id', $productId)
650
-            ->update(['content' => $detail]);
651
-
652
-        return true;
653
-    }
654
-
655
-    /**
656
-     * 处理需要下架的商品(第三方已下架)
657
-     */
658
-    protected function handleOfflineProducts($localSpuIds, $syncedSpuIds)
659
-    {
660
-        $offlineSpuIds = array_diff($localSpuIds, $syncedSpuIds);
661
-
662
-        if (empty($offlineSpuIds)) {
663
-            return;
664
-        }
665
-
666
-        foreach ($offlineSpuIds as $spuId) {
667
-            $this->offlineProductBySpuId($spuId, 'third_party_offline');
668
-        }
409
+        // foreach ($offlineSpuIds as $spuId) {
410
+        //     $this->offlineProductBySpuId($spuId, 'third_party_offline');
411
+        // }
669 412
 
670 413
         Log::info("下架第三方已下架商品" . json_encode(['count' => count($offlineSpuIds), 'spu_ids' => $offlineSpuIds]));
671 414
     }
672 415
 
673 416
     /**
674
-     * 根据SPU ID下架商品
675
-     */
676
-    protected function offlineProductBySpuId($spuId, $reason)
677
-    {
678
-        // 查找已上架的商品
679
-        $products = Db::name('store_product')
680
-            ->where('spu_id', $spuId)
681
-            ->select();
682
-        $douhuomallData = Db::name('douhuomall')->where('spu_id', $spuId)->select()->toArray();
683
-
684
-        foreach ($products as $product) {
685
-            // 下架商品
686
-            Db::name('store_product')
687
-                ->where('product_id', $product['product_id'])
688
-                ->update([
689
-                    'is_show' => ProductEnum::IS_SHOW['No']['code'],
690
-                    'status' => ProductEnum::STATUS['Withdrawn']['code'],
691
-                    'is_status' => ProductEnum::IS_STATUS['Automatic']['code']
692
-                ]);
693
-
694
-            // 记录日志
695
-            $this->recordChangeLog(
696
-                $product['product_id'],
697
-                $spuId,
698
-                'third_party_offline',
699
-                $reason,
700
-                ['product' => $product, 'douhuomallData' => $douhuomallData],
701
-                []
702
-            );
703
-        }
704
-
705
-        // 从douhuomall表中删除
706
-        Db::name('douhuomall')->where('spu_id', $spuId)->delete();
707
-    }
708
-
709
-    /**
710
-     * 记录变动日志
711
-     */
712
-    protected function recordChangeLog($productId, $spuId, $changeType, $reason, $beforeData, $afterData)
713
-    {
714
-        $logData = [
715
-            'product_id' => $productId,
716
-            'spu_id' => $spuId,
717
-            'change_type' => $changeType,
718
-            'change_reason' => $reason,
719
-            'before_data' => json_encode($beforeData, JSON_UNESCAPED_UNICODE),
720
-            'after_data' => json_encode($afterData, JSON_UNESCAPED_UNICODE),
721
-            'change_time' => time(),
722
-            'create_time' => time()
723
-        ];
724
-
725
-        Db::name('product_change_log')->insert($logData);
726
-    }
727
-
728
-    /**
729 417
      * 数组排序(从原有add方法中提取)
730 418
      */
731 419
     protected function arrSort($array, $keys, $sort = SORT_DESC)

+ 15 - 0
app/common/dao/douhuomall/DouhuomallChangeLogDao.php

@@ -0,0 +1,15 @@
1
+<?php
2
+
3
+namespace app\common\dao\douhuomall;
4
+
5
+use app\common\dao\BaseDao;
6
+use app\common\model\douhuomall\DouhuomallChangeLog;
7
+
8
+class DouhuomallChangeLogDao extends BaseDao
9
+{
10
+
11
+    protected function getModel(): string
12
+    {
13
+        return DouhuomallChangeLog::class;
14
+    }
15
+}

+ 15 - 0
app/common/dao/store/product/ProductAttrValueChangeLogDao.php

@@ -0,0 +1,15 @@
1
+<?php
2
+
3
+namespace app\common\dao\store\product;
4
+
5
+use app\common\dao\BaseDao;
6
+use app\common\model\store\product\ProductAttrValueChangeLog as model;
7
+
8
+class ProductAttrValueChangeLogDao extends BaseDao
9
+{
10
+
11
+    protected function getModel(): string
12
+    {
13
+        return model::class;
14
+    }
15
+}

+ 13 - 0
app/common/enum/douhuomall/DouhuomallChangeLogEnum.php

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+namespace app\common\enum\douhuomall;
4
+
5
+use app\common\enum\CommonEnum;
6
+
7
+class DouhuomallChangeLogEnum extends CommonEnum
8
+{
9
+    const TYPE = [
10
+        'Adjust' => ['code' => 1, 'name' => '调价'],
11
+        'Delete' => ['code' => 2, 'name' => '删除']
12
+    ];
13
+}

+ 19 - 0
app/common/model/douhuomall/DouhuomallChangeLog.php

@@ -0,0 +1,19 @@
1
+<?php
2
+
3
+namespace app\common\model\douhuomall;
4
+
5
+use app\common\model\BaseModel;
6
+
7
+class DouhuomallChangeLog extends BaseModel
8
+{
9
+
10
+    public static function tablePk(): string
11
+    {
12
+        return '';
13
+    }
14
+
15
+    public static function tableName(): string
16
+    {
17
+        return 'douhuomall_change_logs';
18
+    }
19
+}

+ 19 - 0
app/common/model/store/product/ProductAttrValueChangeLog.php

@@ -0,0 +1,19 @@
1
+<?php
2
+
3
+namespace app\common\model\store\product;
4
+
5
+use app\common\model\BaseModel;
6
+
7
+class ProductAttrValueChangeLog extends BaseModel
8
+{
9
+
10
+    public static function tablePk(): string
11
+    {
12
+        return '';
13
+    }
14
+
15
+    public static function tableName(): string
16
+    {
17
+        return 'store_product_attr_value_change_logs';
18
+    }
19
+}

+ 39 - 0
app/common/repositories/douhuomall/DouhuomallChangeLogRepository.php

@@ -0,0 +1,39 @@
1
+<?php
2
+
3
+namespace app\common\repositories\douhuomall;
4
+
5
+use app\common\dao\douhuomall\DouhuomallChangeLogDao;
6
+use app\common\repositories\BaseRepository;
7
+use app\entity\data\douhuomall\DouhuomallChangeLogEntity;
8
+
9
+class DouhuomallChangeLogRepository extends BaseRepository
10
+{
11
+
12
+    protected $dao;
13
+
14
+    /**
15
+     * DouhuomallChangeLogRepository constructor.
16
+     * @param DouhuomallChangeLogDao $dao
17
+     */
18
+    public function __construct(DouhuomallChangeLogDao $dao)
19
+    {
20
+        $this->dao = $dao;
21
+    }
22
+
23
+    public function create($data)
24
+    {
25
+        return $this->dao->create($data);
26
+    }
27
+
28
+    /**
29
+     * @param DouhuomallChangeLogEntity $douhuomallChangeLogEntity
30
+     * @return DouhuomallChangeLogEntity
31
+     */
32
+    public function createByEntity(DouhuomallChangeLogEntity $douhuomallChangeLogEntity): DouhuomallChangeLogEntity
33
+    {
34
+        $result = $this->create($douhuomallChangeLogEntity->toUnderlineArray())->toArray();
35
+        /** @var DouhuomallChangeLogEntity $entity */
36
+        $entity = DouhuomallChangeLogEntity::newInstance($result);
37
+        return $entity;
38
+    }
39
+}

+ 39 - 0
app/common/repositories/store/product/ProductAttrValueChangeLogRepository.php

@@ -0,0 +1,39 @@
1
+<?php
2
+
3
+namespace app\common\repositories\store\product;
4
+
5
+use app\common\repositories\BaseRepository;
6
+use app\common\dao\store\product\ProductAttrValueChangeLogDao;
7
+use app\entity\data\store\StoreProductAttrValueChangeLogEntity;
8
+
9
+class ProductAttrValueChangeLogRepository extends BaseRepository
10
+{
11
+
12
+    protected $dao;
13
+
14
+    /**
15
+     * ProductAttrValueChangeLogRepository constructor.
16
+     * @param ProductAttrValueChangeLogDao $dao
17
+     */
18
+    public function __construct(ProductAttrValueChangeLogDao $dao)
19
+    {
20
+        $this->dao = $dao;
21
+    }
22
+
23
+    public function create($data)
24
+    {
25
+        return $this->dao->create($data);
26
+    }
27
+
28
+    /**
29
+     * @param StoreProductAttrValueChangeLogEntity $storeProductAttrValueChangeLogEntity
30
+     * @return StoreProductAttrValueChangeLogEntity
31
+     */
32
+    public function createByEntity(StoreProductAttrValueChangeLogEntity $storeProductAttrValueChangeLogEntity): StoreProductAttrValueChangeLogEntity
33
+    {
34
+        $result = $this->create($storeProductAttrValueChangeLogEntity->toUnderlineArray())->toArray();
35
+        /** @var StoreProductAttrValueChangeLogEntity $entity */
36
+        $entity = StoreProductAttrValueChangeLogEntity::newInstance($result);
37
+        return $entity;
38
+    }
39
+}

+ 15 - 2
app/common/repositories/store/product/ProductRepository.php

@@ -23,6 +23,7 @@ use app\common\repositories\user\UserVisitRepository;
23 23
 use app\common\repositories\wechat\RoutineQrcodeRepository;
24 24
 use app\common\repositories\wechat\WechatQrcodeRepository;
25 25
 use app\controller\merchant\gong\Goods;
26
+use app\entity\data\store\StoreProductAttrValueChangeLogEntity;
26 27
 use app\entity\data\store\StoreProductEntity;
27 28
 use app\traits\ShouxinyiApiRequest;
28 29
 use crmeb\exceptions\ApiException;
@@ -1965,7 +1966,7 @@ class ProductRepository extends BaseRepository
1965 1966
         return set_price_rtrim($yanglao);
1966 1967
     }
1967 1968
 
1968
-    public function editPrice($product_id, $skuArr, $type = 1)
1969
+    public function editPrice($product_id, $skuArr, $type = 1, $operatorId = 0)
1969 1970
     {
1970 1971
         if (empty($skuArr))
1971 1972
             throw new ApiException('参数错误');
@@ -1977,6 +1978,8 @@ class ProductRepository extends BaseRepository
1977 1978
                 ->select()->toArray();
1978 1979
             $attrInfo = array_column($attrInfo, null, 'gong_sku_id');
1979 1980
             $updateData = [];
1981
+            /** @var ProductAttrValueChangeLogRepository $productAttrValueChangeLogRepository */
1982
+            $productAttrValueChangeLogRepository = app()->make(ProductAttrValueChangeLogRepository::class);
1980 1983
             // 组装数据
1981 1984
             foreach ($skuArr as $key => $value) {
1982 1985
                 if (isset($attrInfo[$value['sku_id']])) {
@@ -1995,7 +1998,17 @@ class ProductRepository extends BaseRepository
1995 1998
                             throw new ApiException('销售价格填写不正确');
1996 1999
                         }
1997 2000
                     }
1998
-
2001
+                    /** @var StoreProductAttrValueChangeLogEntity $storeProductAttrValueChangeLogEntity */
2002
+                    $storeProductAttrValueChangeLogEntity = StoreProductAttrValueChangeLogEntity::newInstance();
2003
+                    $storeProductAttrValueChangeLogEntity->setProductId($product_id)
2004
+                        ->setSkuId($value['sku_id'])
2005
+                        ->setCost($attrInfo[$value['sku_id']]['cost'])
2006
+                        ->setOtPrice($attrInfo[$value['sku_id']]['ot_price'])
2007
+                        ->setPrice($attrInfo[$value['sku_id']]['price'])
2008
+                        ->setPlateMerProfit($attrInfo[$value['sku_id']]['plate_mer_profit'])
2009
+                        ->setOperatorId($operatorId)
2010
+                        ->setCreateTime(date('Y-m-d H:i:s'));
2011
+                    $productAttrValueChangeLogRepository->createByEntity($storeProductAttrValueChangeLogEntity);
1999 2012
                     $updateData[] = [
2000 2013
                         'gong_sku_id'      => $value['sku_id'],
2001 2014
                         'price'            => $value['edit_price'],

+ 3 - 2
app/controller/merchant/store/product/Product.php

@@ -78,11 +78,12 @@ class Product extends BaseController
78 78
     {
79 79
         $skuArr = $this->request->param('skuArr', []);
80 80
         $type = $this->request->param('type');
81
+        $merchant_admin_id = $this->request->adminInfo()?$this->request->adminInfo()->merchant_admin_id:0;
81 82
 
82 83
         if (empty($skuArr) ||  !is_array($skuArr)) {
83 84
             return app('json')->fail('参数错误');
84 85
         }
85
-        $this->repository->editPrice($id, $skuArr, $type);
86
+        $this->repository->editPrice($id, $skuArr, $type, $merchant_admin_id);
86 87
         return app('json')->success("修改成功");
87 88
     }
88 89
 
@@ -90,7 +91,7 @@ class Product extends BaseController
90 91
     // 供应链商品删除
91 92
     public function deleteXp($id) {
92 93
         if (empty($id)) return app('json')->fail('请选择商品');
93
-        $this->repository->changeDelete($id,);
94
+        $this->repository->changeDelete($id);
94 95
         return app('json')->success('删除成功');
95 96
     }
96 97
 

+ 110 - 0
app/entity/data/douhuomall/DouhuomallChangeLogEntity.php

@@ -0,0 +1,110 @@
1
+<?php
2
+
3
+namespace app\entity\data\douhuomall;
4
+
5
+use app\entity\data\DataEntity;
6
+
7
+class DouhuomallChangeLogEntity extends DataEntity
8
+{
9
+    public $id = null;  // 主键ID
10
+    public $spuId = null;  // spuID
11
+    public $dataJson = null;  // 历史数据信息
12
+    public $effectProductJson = null;  // 供应链sku_id
13
+    public $createTime = null;  // 记录时间
14
+
15
+    /**
16
+     * @return mixed
17
+     */
18
+    public function getId()
19
+    {
20
+        return $this->id;
21
+    }
22
+
23
+    /**
24
+     * @param mixed $id
25
+     * @return DouhuomallChangeLogEntity
26
+     */
27
+    public function setId($id): DouhuomallChangeLogEntity
28
+    {
29
+        $this->id = $id;
30
+        return $this;
31
+    }
32
+
33
+    /**
34
+     * @return mixed
35
+     */
36
+    public function getSpuId()
37
+    {
38
+        return $this->spuId;
39
+    }
40
+
41
+    /**
42
+     * @param mixed $spuId
43
+     * @return DouhuomallChangeLogEntity
44
+     */
45
+    public function setSpuId($spuId): DouhuomallChangeLogEntity
46
+    {
47
+        $this->spuId = $spuId;
48
+        return $this;
49
+    }
50
+
51
+    /**
52
+     * @return mixed
53
+     */
54
+    public function getDataJson()
55
+    {
56
+        return $this->dataJson;
57
+    }
58
+
59
+    /**
60
+     * @param mixed $dataJson
61
+     * @return DouhuomallChangeLogEntity
62
+     */
63
+    public function setDataJson($dataJson): DouhuomallChangeLogEntity
64
+    {
65
+        if (is_array($dataJson)) {
66
+            $dataJson = json_encode($dataJson, JSON_UNESCAPED_UNICODE);
67
+        }
68
+        $this->dataJson = $dataJson;
69
+        return $this;
70
+    }
71
+
72
+    /**
73
+     * @return mixed
74
+     */
75
+    public function getEffectProductJson()
76
+    {
77
+        return $this->effectProductJson;
78
+    }
79
+
80
+    /**
81
+     * @param mixed $effectProductJson
82
+     * @return DouhuomallChangeLogEntity
83
+     */
84
+    public function setEffectProductJson($effectProductJson): DouhuomallChangeLogEntity
85
+    {
86
+        if (is_array($effectProductJson)) {
87
+            $effectProductJson = json_encode($effectProductJson, JSON_UNESCAPED_UNICODE);
88
+        }
89
+        $this->effectProductJson = $effectProductJson;
90
+        return $this;
91
+    }
92
+
93
+    /**
94
+     * @return mixed
95
+     */
96
+    public function getCreateTime()
97
+    {
98
+        return $this->createTime;
99
+    }
100
+
101
+    /**
102
+     * @param mixed $createTime
103
+     * @return DouhuomallChangeLogEntity
104
+     */
105
+    public function setCreateTime($createTime): DouhuomallChangeLogEntity
106
+    {
107
+        $this->createTime = $createTime;
108
+        return $this;
109
+    }
110
+}

+ 180 - 0
app/entity/data/store/StoreProductAttrValueChangeLogEntity.php

@@ -0,0 +1,180 @@
1
+<?php
2
+
3
+namespace app\entity\data\store;
4
+
5
+use app\entity\data\DataEntity;
6
+
7
+class StoreProductAttrValueChangeLogEntity extends DataEntity
8
+{
9
+    public $id = null;  // 主键ID
10
+    public $productId = null;  // 商品ID
11
+    public $skuId = null;  // 供应链sku_id
12
+    public $cost = null;  // 成本价
13
+    public $otPrice = null;  // 原价
14
+    public $price = null;  // 价格
15
+    public $plateMerProfit = null;  // 商户创客利润
16
+    public $operatorId = null;  // 操作人ID
17
+    public $createTime = null;  // 记录时间
18
+
19
+    /**
20
+     * @return mixed
21
+     */
22
+    public function getId()
23
+    {
24
+        return $this->id;
25
+    }
26
+
27
+    /**
28
+     * @param mixed $id
29
+     * @return StoreProductAttrValueChangeLogEntity
30
+     */
31
+    public function setId($id): StoreProductAttrValueChangeLogEntity
32
+    {
33
+        $this->id = $id;
34
+        return $this;
35
+    }
36
+
37
+    /**
38
+     * @return mixed
39
+     */
40
+    public function getProductId()
41
+    {
42
+        return $this->productId;
43
+    }
44
+
45
+    /**
46
+     * @param mixed $productId
47
+     * @return StoreProductAttrValueChangeLogEntity
48
+     */
49
+    public function setProductId($productId): StoreProductAttrValueChangeLogEntity
50
+    {
51
+        $this->productId = $productId;
52
+        return $this;
53
+    }
54
+
55
+    /**
56
+     * @return mixed
57
+     */
58
+    public function getSkuId()
59
+    {
60
+        return $this->skuId;
61
+    }
62
+
63
+    /**
64
+     * @param mixed $skuId
65
+     * @return StoreProductAttrValueChangeLogEntity
66
+     */
67
+    public function setSkuId($skuId): StoreProductAttrValueChangeLogEntity
68
+    {
69
+        $this->skuId = $skuId;
70
+        return $this;
71
+    }
72
+
73
+    /**
74
+     * @return mixed
75
+     */
76
+    public function getCost()
77
+    {
78
+        return $this->cost;
79
+    }
80
+
81
+    /**
82
+     * @param mixed $cost
83
+     * @return StoreProductAttrValueChangeLogEntity
84
+     */
85
+    public function setCost($cost): StoreProductAttrValueChangeLogEntity
86
+    {
87
+        $this->cost = $cost;
88
+        return $this;
89
+    }
90
+
91
+    /**
92
+     * @return mixed
93
+     */
94
+    public function getOtPrice()
95
+    {
96
+        return $this->otPrice;
97
+    }
98
+
99
+    /**
100
+     * @param mixed $otPrice
101
+     * @return StoreProductAttrValueChangeLogEntity
102
+     */
103
+    public function setOtPrice($otPrice): StoreProductAttrValueChangeLogEntity
104
+    {
105
+        $this->otPrice = $otPrice;
106
+        return $this;
107
+    }
108
+
109
+    /**
110
+     * @return mixed
111
+     */
112
+    public function getPrice()
113
+    {
114
+        return $this->price;
115
+    }
116
+
117
+    /**
118
+     * @param mixed $price
119
+     * @return StoreProductAttrValueChangeLogEntity
120
+     */
121
+    public function setPrice($price): StoreProductAttrValueChangeLogEntity
122
+    {
123
+        $this->price = $price;
124
+        return $this;
125
+    }
126
+
127
+    /**
128
+     * @return mixed
129
+     */
130
+    public function getPlateMerProfit()
131
+    {
132
+        return $this->plateMerProfit;
133
+    }
134
+
135
+    /**
136
+     * @param mixed $plateMerProfit
137
+     * @return StoreProductAttrValueChangeLogEntity
138
+     */
139
+    public function setPlateMerProfit($plateMerProfit): StoreProductAttrValueChangeLogEntity
140
+    {
141
+        $this->plateMerProfit = $plateMerProfit;
142
+        return $this;
143
+    }
144
+
145
+    /**
146
+     * @return mixed
147
+     */
148
+    public function getOperatorId()
149
+    {
150
+        return $this->operatorId;
151
+    }
152
+
153
+    /**
154
+     * @param mixed $operatorId
155
+     * @return StoreProductAttrValueChangeLogEntity
156
+     */
157
+    public function setOperatorId($operatorId): StoreProductAttrValueChangeLogEntity
158
+    {
159
+        $this->operatorId = $operatorId;
160
+        return $this;
161
+    }
162
+
163
+    /**
164
+     * @return mixed
165
+     */
166
+    public function getCreateTime()
167
+    {
168
+        return $this->createTime;
169
+    }
170
+
171
+    /**
172
+     * @param mixed $createTime
173
+     * @return StoreProductAttrValueChangeLogEntity
174
+     */
175
+    public function setCreateTime($createTime): StoreProductAttrValueChangeLogEntity
176
+    {
177
+        $this->createTime = $createTime;
178
+        return $this;
179
+    }
180
+}