Explorar el Código

分批次同步数据

LAPTOP-VT1IP978\suxio hace 2 semanas
padre
commit
54b891bb7b

+ 33 - 0
app/Console/Commands/SyncSealDrugReportCommand.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\SyncSealDrugReportService;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+
+class SyncSealDrugReportCommand extends Command
+{
+    // php artisan sync:seal-drug-report --start-time="2025-03-01 00:00:00" --end-time="2025-03-31 23:59:59"
+    protected $signature = 'sync:seal-drug-report {--start-time=} {--end-time=} {--page=1} {--page-size=20}';
+
+    protected $description = '同步已签收药检报告数据';
+
+    public function handle(SyncSealDrugReportService $service): int
+    {
+        $startTime = $this->option('start-time') ?? Carbon::today()->startOfDay();
+        $endTime = $this->option('end-time') ?? Carbon::now();
+        $page = $this->option('page') ?? 1;
+        $pageSize = $this->option('page-size') ?? 20;
+
+        echo sprintf('已签收药检报告数据[%s, %s, %d, %d]:', $startTime, $endTime, $page, $pageSize), PHP_EOL;
+        echo "全量同步开始……", PHP_EOL;
+
+        $count = $service->syncSealDrugReport($startTime, $endTime, $page, $pageSize);
+
+        echo "全量同步结束,共处理 {$count} 条记录!", PHP_EOL;
+
+        return Command::SUCCESS;
+    }
+
+}

+ 11 - 11
app/Http/Controllers/AlihealthController.php → app/Http/Controllers/QueryDrugReportController.php

@@ -2,22 +2,22 @@
 
 namespace App\Http\Controllers;
 
-use App\Services\AlihealthService;
+use App\Services\QueryDrugReportService;
 use Carbon\Carbon;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 
-class AlihealthController extends Controller
+class QueryDrugReportController extends Controller
 {
     /**
      * 查询上游企业的待签收药检报告信息
      * (?begin_time=2025-11-01 00:00:00&end_time=2025-11-31 23:59:59&page=1&page_size=20)
      * @param Request $request
-     * @param AlihealthService $service
+     * @param QueryDrugReportService $service
      * @return JsonResponse
      * @throws \Exception
      */
-    public function queryDrugReport(Request $request, AlihealthService $service)
+    public function queryDrugReport(Request $request, QueryDrugReportService $service)
     {
         $beginTime = $request->get("begin_time") ?? Carbon::now()->startOfMonth()->toDateTimeString();
         $endTime = $request->get("end_time") ?? Carbon::now()->endOfMonth()->toDateTimeString();
@@ -25,18 +25,18 @@ class AlihealthController extends Controller
         $pageSize = $request->get("page_size") ?? 20;
         $data = $service->queryDrugReport($beginTime, $endTime, $page, $pageSize);
         dd($data);
-        return response()->json($data);
+//        return response()->json($data);
     }
 
     /**
      * 查询上传报告信息接口
      * (?begin_time=2025-03-01 00:00:00&end_time=2025-03-31 23:59:59&page=1&page_size=20&is_seal=0)
      * @param Request $request
-     * @param AlihealthService $service
+     * @param QueryDrugReportService $service
      * @return JsonResponse
      * @throws \Exception
      */
-    public function querySealDrugReport(Request $request, AlihealthService $service)
+    public function querySealDrugReport(Request $request, QueryDrugReportService $service)
     {
         $beginTime = $request->get("begin_time") ?? Carbon::now()->startOfMonth()->toDateTimeString();
         $endTime = $request->get("end_time") ?? Carbon::now()->endOfMonth()->toDateTimeString();
@@ -45,18 +45,18 @@ class AlihealthController extends Controller
         $isSeal = $request->get("is_seal") ?? 0;
         $data = $service->querySealDrugReport($beginTime, $endTime, $page, $pageSize, $isSeal);
         dd($data);
-        return response()->json($data);
+//        return response()->json($data);
     }
 
     /**
      * 药检报告操作日志
      * (?begin_date=2025-11-01&end_date=2025-11-31&page=1&page_size=20)
      * @param Request $request
-     * @param AlihealthService $service
+     * @param QueryDrugReportService $service
      * @return JsonResponse
      * @throws \Exception
      */
-    public function drugReportOptHistory(Request $request, AlihealthService $service)
+    public function drugReportOptHistory(Request $request, QueryDrugReportService $service)
     {
         $beginDate = $request->get("begin_date") ?? Carbon::now()->startOfMonth()->toDateString();
         $endDate = $request->get("end_date") ?? Carbon::now()->endOfMonth()->toDateString();
@@ -64,6 +64,6 @@ class AlihealthController extends Controller
         $pageSize = $request->get("page_size") ?? 20;
         $data = $service->drugReportOptHistory($beginDate, $endDate, $page, $pageSize);
         dd($data);
-        return response()->json($data);
+//        return response()->json($data);
     }
 }

+ 29 - 0
app/Models/DrugReportInfo.php

@@ -5,6 +5,7 @@ namespace App\Models;
 use App\Traits\Filterable;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\DB;
 
 /**
  * App\Models\DrugReportInfo
@@ -103,4 +104,32 @@ class DrugReportInfo extends Model
      * @var array|string[] 定义可搜索字段(可选,可在调用时覆盖)
      */
     public static $searchable = ['id'];
+
+    /**
+     * 批量更新或插入
+     * @param array $data
+     * @param array $uniqueKeys
+     * @return int
+     * @throws \Throwable
+     */
+    public static function bulkUpsert(array $data, array $uniqueKeys = ['batch_no', 'drug_id']): int
+    {
+        if (empty($data)) {
+            return 0;
+        }
+
+        return DB::transaction(function () use ($data, $uniqueKeys) {
+            $count = 0;
+            foreach (array_chunk($data, 100) as $chunk) {
+                self::upsert(
+                    $chunk,
+                    $uniqueKeys, // 组合唯一键
+                    array_keys($data[0]) // 要更新的字段
+                );
+                $count += count($chunk);
+            }
+
+            return $count;
+        });
+    }
 }

+ 0 - 43
app/Services/DrugReportInfoService.php

@@ -8,49 +8,6 @@ use Illuminate\Support\Facades\DB;
 
 class DrugReportInfoService
 {
-    /*public function bulkUpsert(array $data, array $uniqueKeys = ['key1', 'key2'])
-    {
-        return DB::transaction(function () use ($data, $uniqueKeys) {
-            foreach (array_chunk($data, 100) as $chunk) {
-                DrugReportInfo::upsert(
-                    $chunk,
-                    $uniqueKeys, // 组合唯一键
-                    array_keys($data[0]) // 要更新的字段
-                );
-            }
-
-            return true;
-        });
-    }*/
-
-    public function bulkInsert(array $data): bool
-    {
-        $data = self::correct($data);
-        return DrugReportInfo::insert($data);
-    }
-
-    public static function correct(array $data): array
-    {
-        return array_map(function ($item) {
-            return [
-                'drug_report_v2_id' => $item['drug_report_v2_id'] ?? '',
-                'report_id' => $item['report_id'] ?? '',
-                'report_name' => $item['drug_report_name'] ?? '',
-                'report_no' => $item['report_no'] ?? '',
-                'report_date' => $item['report_date'] ?? '',
-                'batch_no' => $item['batch_no'] ?? '',
-                'drug_id' => $item['drug_ent_base_info_id'] ?? '',
-                'drug_name' => $item['drug_name'] ?? '',
-                'prod_code' => $item['prod_code'] ?? '',
-                'pkg_spec' => $item['pkg_spec'] ?? '',
-                'prepn_spec' => $item['prepn_spec'] ?? '',
-                'pkg_ratio_list' => json_encode($item['pkg_ratio_list'] ?? [], JSON_UNESCAPED_UNICODE),
-                'sealed_report_url' => $item['sealed_report_url'] ?? '',
-                'seal_raw_data' => json_encode($data ?? [], JSON_UNESCAPED_UNICODE),
-            ];
-        }, $data);
-    }
-
     public function getList(array $filters, string $search, array $sort, int $perPage) {
         $options = array_merge([
             'search' => $search,

+ 1 - 1
app/Services/AlihealthService.php → app/Services/QueryDrugReportService.php

@@ -8,7 +8,7 @@ use AlibabaAlihealthSynergyYzwQuerysealdrugreportRequest;
 use Page;
 use TopClient;
 
-class AlihealthService
+class QueryDrugReportService
 {
     private $client;
 

+ 134 - 0
app/Services/SyncSealDrugReportService.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\DrugReportInfo;
+use Illuminate\Support\Facades\Log;
+
+class SyncSealDrugReportService
+{
+    protected $source = 'querysealdrugreport';
+
+    /**
+     * 分批次同步数据
+     * @param string $startTime
+     * @param string $endTime
+     * @param int $page
+     * @param int $pageSize
+     * @return int
+     */
+    public function syncSealDrugReport(string $startTime, string $endTime, int $page, int $pageSize): int
+    {
+        $hasMore = true;
+        $total = 0;
+
+        Log::channel('sync')->warning("开始全量同步", [
+            'source' => $this->source,
+            'params' => [
+                'start_time' => $startTime,
+                'end_time' => $endTime,
+                'page' => $page,
+                'page_size' => $pageSize,
+            ],
+        ]);
+
+        $queryDrugReportService = app(QueryDrugReportService::class);
+
+        while ($hasMore) {
+            try {
+                // 分批次拉取数据
+                $data = $queryDrugReportService->querySealDrugReport($startTime, $endTime, $page, $pageSize);
+                if (empty($data)) {
+                    $hasMore = false;
+                    break;
+                }
+
+                // 处理并保存数据
+                $saveCount = $this->saveSealDrugReport($data);
+                $total += $saveCount;
+
+                Log::channel('sync')->info("批次 {$page} 处理完成", [
+                    'source' => $this->source,
+                    'fetch_count' => count($data),
+                    'save_count' => $saveCount,
+                    'total' => $total
+                ]);
+
+                // 检查是否还有更多数据
+                $hasMore = (count($data) === $pageSize);
+
+                $page++;
+                break;
+
+                // 避免请求过于频繁
+                sleep(1);
+
+            } catch (\Exception $e) {
+                Log::channel('sync')->error('获取批次数据失败', [
+                    'source' => $this->source,
+                    'params' => [
+                        'start_time' => $startTime,
+                        'end_time' => $endTime,
+                        'page' => $page,
+                        'page_size' => $pageSize,
+                    ],
+                    'error' => $e->getMessage()
+                ]);
+                continue;
+            }
+        }
+
+        Log::channel('sync')->warning("全量同步完成", [
+            'source' => $this->source,
+            'total' => $total
+        ]);
+
+        return $total;
+    }
+
+    /**
+     * 处理并保存批次数据
+     * @param array $data
+     * @return int
+     */
+    protected function saveSealDrugReport(array $data): int
+    {
+        try {
+            $data = $this->correctSealDrugReport($data);
+            return DrugReportInfo::bulkUpsert($data);
+        } catch (\Throwable $e) {
+            Log::channel('sync')->error("保存批次数据失败", [
+                'data' => $data,
+                'error' => $e->getMessage()
+            ]);
+            return 0;
+        }
+    }
+
+    /**
+     * 处理批次数据
+     * @param array $data
+     * @return array
+     */
+    protected function correctSealDrugReport(array $data): array
+    {
+        return array_map(function ($item) {
+            return [
+                'drug_report_v2_id' => $item['drug_report_v2_id'] ?? '',
+                'report_id' => $item['report_id'] ?? '',
+                'report_name' => $item['drug_report_name'] ?? '',
+                'report_no' => $item['report_no'] ?? '',
+                'report_date' => $item['report_date'] ?? '',
+                'batch_no' => $item['batch_no'] ?? '',
+                'drug_id' => $item['drug_ent_base_info_id'] ?? '',
+                'drug_name' => $item['drug_name'] ?? '',
+                'prod_code' => $item['prod_code'] ?? '',
+                'pkg_spec' => $item['pkg_spec'] ?? '',
+                'prepn_spec' => $item['prepn_spec'] ?? '',
+                'pkg_ratio_list' => json_encode($item['pkg_ratio_list'] ?? [], JSON_UNESCAPED_UNICODE),
+                'sealed_report_url' => $item['sealed_report_url'] ?? '',
+                'seal_raw_data' => json_encode($data ?? [], JSON_UNESCAPED_UNICODE),
+            ];
+        }, $data);
+    }
+}

+ 1 - 1
config/logging.php

@@ -97,7 +97,7 @@ return [
         ],
 
         'emergency' => [
-            'path' => storage_path('logs/laravel.log'),
+            'path' => storage_path('logs/error.log'),
         ],
 
         'sql' => [

+ 4 - 4
routes/api.php

@@ -1,6 +1,6 @@
 <?php
 
-use App\Http\Controllers\AlihealthController;
+use App\Http\Controllers\QueryDrugReportController;
 use App\Http\Controllers\DrugReportInfoController;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Route;
@@ -21,9 +21,9 @@ Route::middleware('auth:api')->get('/user', function (Request $request) {
 });
 
 Route::prefix('ali-health')->group(function () {
-    Route::get('query-drug-report', [AlihealthController::class, 'queryDrugReport']);
-    Route::get('query-seal-drug-report', [AlihealthController::class, 'querySealDrugReport']);
-    Route::get('drug-report-opt-history', [AlihealthController::class, 'drugReportOptHistory']);
+    Route::get('query-drug-report', [QueryDrugReportController::class, 'queryDrugReport']);
+    Route::get('query-seal-drug-report', [QueryDrugReportController::class, 'querySealDrugReport']);
+    Route::get('drug-report-opt-history', [QueryDrugReportController::class, 'drugReportOptHistory']);
 });
 
 Route::prefix('drug-report-info')->group(function () {