diff --git a/app/Classes/General/Eloquent/Filters/OrderTrackingId.php b/app/Classes/General/Eloquent/Filters/OrderTrackingId.php new file mode 100644 index 00000000..137ed17b --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OrderTrackingId.php @@ -0,0 +1,20 @@ +where('order_tracking_id', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/TrackingNo.php b/app/Classes/General/Eloquent/Filters/TrackingNo.php new file mode 100644 index 00000000..d41655bf --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/TrackingNo.php @@ -0,0 +1,23 @@ +where('tracking_no', $value) + ->where(function ($query) { + $query->whereNotNull('tracking_english') + ->orWhereNotNull('remark_english'); + }); + } +} diff --git a/app/Classes/Jobs/Commands/V2/YD/FetchByTrakingNoYdPortalV2CommandJob.php b/app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByPackingListV2CommandJob.php similarity index 83% rename from app/Classes/Jobs/Commands/V2/YD/FetchByTrakingNoYdPortalV2CommandJob.php rename to app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByPackingListV2CommandJob.php index 78a4451f..dc1423ea 100644 --- a/app/Classes/Jobs/Commands/V2/YD/FetchByTrakingNoYdPortalV2CommandJob.php +++ b/app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByPackingListV2CommandJob.php @@ -11,7 +11,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; -class FetchByTrakingNoYdPortalV2CommandJob implements ShouldQueue +class FetchTrakingInfoYDByPackingListV2CommandJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -24,7 +24,7 @@ class FetchByTrakingNoYdPortalV2CommandJob implements ShouldQueue public function handle() { - Log::info('Processing FetchByTrakingNoYdPortalV2CommandJob'); + Log::info('Processing FetchTrakingInfoYDByPackingListV2CommandJob'); $processor = app(FetchByTrakingNoYdPortalV2Processor::class); $processor->execute($this->packingList); } diff --git a/app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByTrackingNoV2CommandJob.php b/app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByTrackingNoV2CommandJob.php new file mode 100644 index 00000000..7c6993a6 --- /dev/null +++ b/app/Classes/Jobs/Commands/V2/YD/FetchTrakingInfoYDByTrackingNoV2CommandJob.php @@ -0,0 +1,30 @@ +trackingNo = $trackingNo; + } + + public function handle() + { + Log::info('Processing FetchTrakingInfoYDByTrackingNoV2CommandJob'); + $processor = app(FetchByTrakingNoYdPortalV2Processor::class); + $processor->processTrackingNo($this->trackingNo); + } +} diff --git a/app/Classes/Modules/Orders/ControllersLogic/ListOrderTrackingLogic.php b/app/Classes/Modules/Orders/ControllersLogic/ListOrderTrackingLogic.php new file mode 100644 index 00000000..85bc2bda --- /dev/null +++ b/app/Classes/Modules/Orders/ControllersLogic/ListOrderTrackingLogic.php @@ -0,0 +1,52 @@ + 'Retrieved Order Tracking', + 'message' => 'You have successfully retrieved order tracking info' + ]; + } + + /** @var ListsOrderTracking */ + private $listsOrderTracking; + + /** + * ListOrderTrackingLogic constructor. + * @param ListsOrderTracking $listsOrderTracking + */ + public function __construct(ListsOrderTracking $listsOrderTracking) + { + $this->listsOrderTracking = $listsOrderTracking; + } + + public function logic(Request $request) : JsonResponse + { + $query = $this->listsOrderTracking->execute($this->listsOrderTracking->deserializeFilters($request->input('filters'))); + + $filters = json_decode($request->input('filters'), true); + $trackingNo = $filters['tracking_no']; + if ($trackingNo) { + Artisan::call('process-yd-by-traking-no-data-command', [ + 'trackingNo' => $trackingNo + ]); + } + + return $this->collectionResponse(OrderTrackingResource::collection($query)); + } +} diff --git a/app/Classes/Modules/Orders/Services/ListsOrderTracking.php b/app/Classes/Modules/Orders/Services/ListsOrderTracking.php new file mode 100644 index 00000000..b402d83b --- /dev/null +++ b/app/Classes/Modules/Orders/Services/ListsOrderTracking.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/PackingLists/Processors/V2/FetchByTrakingNoYdPortalV2Processor.php b/app/Classes/Modules/PackingLists/Processors/V2/FetchByTrakingNoYdPortalV2Processor.php index c0d31e12..ac8e34ae 100644 --- a/app/Classes/Modules/PackingLists/Processors/V2/FetchByTrakingNoYdPortalV2Processor.php +++ b/app/Classes/Modules/PackingLists/Processors/V2/FetchByTrakingNoYdPortalV2Processor.php @@ -40,8 +40,6 @@ class FetchByTrakingNoYdPortalV2Processor Log::info('FetchByTrakingNoYdPortalV2Processor starts with packingList id ' . $packingList->id); // return; - $time_start = microtime(true); - $reference = $packingList->reference; Log::info('reference ' . $reference); @@ -56,15 +54,29 @@ class FetchByTrakingNoYdPortalV2Processor return; } + $this->processTrackingNo($reference); + + Log::info('FetchByTrakingNoYdPortalV2Processor ends with packingList id ' . $packingList->id); + Log::info('---'); + } + + /** + * @param string $reference + * @return void + * @throws MalformedRequestException + */ + public function processTrackingNo(string $reference){ + $time_start = microtime(true); + $check2 = YDOrderTracking::where('tracking_no', $reference) ->where('tracking', '第三方提货') ->first(); - if ($check2) { - Log::info('FetchByTrakingNoYdPortalV2Processor SKIPPED: 第三方提货'); - Log::info('---'); - return; - } + // if ($check2) { + // Log::info('FetchByTrakingNoYdPortalV2Processor SKIPPED: 第三方提货'); + // Log::info('---'); + // return; + // } $trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [ 'trakingno' => $reference @@ -78,11 +90,10 @@ class FetchByTrakingNoYdPortalV2Processor $execution_time = ($time_end - $time_start)/60; - Log::info('FetchByTrakingNoYdPortalV2Processor ends with packingList id ' . $packingList->id . ' => Total Execution Time: '.$execution_time.' Mins.'); - Log::info('---'); + Log::info('FetchByTrakingNoYdPortalV2Processor ends with reference ' . $reference . ' => Total Execution Time: '.$execution_time.' Mins.'); } - public function processData($jsonData, $reference) + private function processData($jsonData, $reference) { $data = json_decode($jsonData, true); @@ -93,23 +104,65 @@ class FetchByTrakingNoYdPortalV2Processor ->where('tracking_no', $reference) ->first(); + // Log::info('tracking: '.$item['tracking']); + // Log::info('remark: '.$item['remark']); + if (!$existingRecord) { $etdEta = $this->parseEtdEta($item['remark'], $item['tracking'], $item['trackingtime']); + $isTrackingTranslatedPreviouly = $this->checkIfTranslationAlreadyExist(!empty($item['tracking']) ? $item['tracking'] : ""); + $isRemarkTranslatedPreviouly = $this->checkIfTranslationAlreadyExist(!empty($item['remark']) ? $item['remark'] : ""); YDOrderTracking::create([ 'order_tracking_id' => $item['Id'], 'tracking_no' => $reference, 'package_id' => $item['package_id'], 'tracking' => $item['tracking'] ?? null, + 'tracking_english' => $isTrackingTranslatedPreviouly ? $isTrackingTranslatedPreviouly : $this->translateTracking($item['tracking']), 'tracking_time' => $item['trackingtime'] ?? null, 'add_time' => $item['addtime'] ?? null, 'remark' => $item['remark'] ?? null, + 'remark_english' => $item['remark'] ? ($isRemarkTranslatedPreviouly ? $isRemarkTranslatedPreviouly : $this->translateTracking($item['remark'])) : null, 'etd' => $etdEta['etd'], 'eta' => $etdEta['eta'] ]); Log::info('FetchByTrakingNoYdPortalV2Processor RECORD CREATED'); } else{ - Log::info('FetchByTrakingNoYdPortalV2Processor RECORD EXIST'); + $isUpdated = false; + if($item['tracking']){ + $isTranslatedPreviouly = $this->checkIfTranslationAlreadyExist(!empty($item['tracking']) ? $item['tracking'] : ""); + $result = $isTranslatedPreviouly; + if (!$isTranslatedPreviouly){ + $result = $this->translateTracking($item['tracking']); + } + if ($result && $existingRecord->tracking_english !== $result) { + $existingRecord->update([ + 'tracking_english' => $result + ]); + $isUpdated = true; + } + } + + if($item['remark']) { + $isTranslatedPreviouly = $this->checkIfTranslationAlreadyExist(!empty($item['remark']) ? $item['remark'] : ""); + $result = $isTranslatedPreviouly; + if (!$isTranslatedPreviouly){ + $result = $this->translateTracking($item['remark']); + } + + if ($result && $existingRecord->remark_english !== $result) { + $existingRecord->update([ + 'remark_english' => $result + ]); + $isUpdated = true; + } + } + + if($isUpdated){ + Log::info('FetchByTrakingNoYdPortalV2Processor RECORD UPDATED'); + } + else{ + Log::info('FetchByTrakingNoYdPortalV2Processor RECORD EXIST'); + } } } } @@ -232,5 +285,44 @@ class FetchByTrakingNoYdPortalV2Processor 'eta' => $eta ? date('Y-m-d', strtotime($eta)) : null, ]; } + + private function checkIfTranslationAlreadyExist($textToTranslate) + { + $returnText = ""; + Log::info('textToTranslate: '.$textToTranslate); + if(!$textToTranslate) return $returnText; + + $translationFound = YDOrderTracking::where('tracking', $textToTranslate)->whereNotNull('tracking_english')->first(); + if(!$translationFound){ + $translationFound = YDOrderTracking::where('remark', $textToTranslate)->whereNotNull('remark_english')->first(); + if($translationFound){ + $returnText = $translationFound->remark_english; + } + } + else{ + $returnText = $translationFound->tracking_english; + } + Log::info('FOUND EXISTING TRANSLATION: '.$returnText); + return $returnText; + } + + private function translateTracking($textToTranslate) + { + $userPrompt = "Please translate mandarin to english and return result in this format, e.g. {'mandarin': '.$textToTranslate.', 'english': ''}. ".$textToTranslate." "; + Log::info('prompt: '.$userPrompt); + $result = $this->createsChatGPTResponse->execute($userPrompt); + Log::info('result (json_encoded): '.json_encode($result)); + $content = $result['choices'][0]['message']['content'] ?? null; + Log::info('content (json_encoded):'. json_encode($content)); + $parsedContent = json_decode(str_replace("'", '"', $content), true); + + if($parsedContent && $parsedContent['english']){ + Log::info('Translated Text: ' . $parsedContent['english']); + return $parsedContent['english']; + } + else{ + return null; + } + } } diff --git a/app/Console/Commands/V2/ProcessYDByTrakingNoDataV2Command.php b/app/Console/Commands/V2/ProcessYDByTrakingNoDataV2Command.php index a4ee8582..b7a12a1c 100644 --- a/app/Console/Commands/V2/ProcessYDByTrakingNoDataV2Command.php +++ b/app/Console/Commands/V2/ProcessYDByTrakingNoDataV2Command.php @@ -3,7 +3,8 @@ namespace App\Console\Commands\V2; -use App\Classes\Jobs\Commands\V2\YD\FetchByTrakingNoYdPortalV2CommandJob; +use App\Classes\Jobs\Commands\V2\YD\FetchTrakingInfoYDByPackingListV2CommandJob; +use App\Classes\Jobs\Commands\V2\YD\FetchTrakingInfoYDByTrackingNoV2CommandJob; use App\Classes\ValueObjects\Constants\PackingListType; use App\Models\PackingList; use Carbon\Carbon; @@ -17,7 +18,7 @@ class ProcessYDByTrakingNoDataV2Command extends Command * * @var string */ - protected $signature = 'process-yd-by-traking-no-data-command'; + protected $signature = 'process-yd-by-traking-no-data-command {trackingNo?}'; /** * The console command description. @@ -33,11 +34,19 @@ class ProcessYDByTrakingNoDataV2Command extends Command */ public function handle() { - $jobs = $this->fetchByTrakingNoYdPortalV2CommandJob(); + $trackingNo = $this->argument('trackingNo'); - foreach ($jobs as $index => $job) { - $delayInSeconds = intdiv($index, 2); - dispatch($job)->delay(now()->addSeconds($delayInSeconds)); + if ($trackingNo) { + dispatch(new FetchTrakingInfoYDByTrackingNoV2CommandJob($trackingNo)); + Log::info("Job dispatched for tracking number: {$trackingNo}"); + } + else { + $jobs = $this->fetchByTrakingNoYdPortalV2CommandJob(); + + foreach ($jobs as $index => $job) { + $delayInSeconds = intdiv($index, 2); + dispatch($job)->delay(now()->addSeconds($delayInSeconds)); + } } } @@ -48,9 +57,13 @@ class ProcessYDByTrakingNoDataV2Command extends Command $packingLists = PackingList::where('type', PackingListType::SHIPPING_PACKING_LIST)->whereDate('created_at', '>=', $maxFetchTime)->get(); $count = 0; foreach ($packingLists as $packingList) { - $jobs[] = new FetchByTrakingNoYdPortalV2CommandJob($packingList); + $jobs[] = new FetchTrakingInfoYDByPackingListV2CommandJob($packingList); Log::info('Dispatched FetchByTrakingNoYdPortalV2CommandJob for packingList with id ' . $packingList->id . ' reference ' . $packingList->reference . ' created_at ' . $packingList->created_at); $count++; + // Log::info('Dispatched count '. $count); + // if ($count === 50) { + // break; + // } } Log::info('Total FetchByTrakingNoYdPortalV2CommandJob dispatched: ' . $count); diff --git a/app/Http/Controllers/Orders/ListOrderTrackingController.php b/app/Http/Controllers/Orders/ListOrderTrackingController.php new file mode 100644 index 00000000..78152965 --- /dev/null +++ b/app/Http/Controllers/Orders/ListOrderTrackingController.php @@ -0,0 +1,22 @@ +execute($request); + } +} diff --git a/app/Http/Resources/OrderTrackingResource.php b/app/Http/Resources/OrderTrackingResource.php new file mode 100644 index 00000000..d68c3b92 --- /dev/null +++ b/app/Http/Resources/OrderTrackingResource.php @@ -0,0 +1,25 @@ + $this->id, + 'tracking_no' => $this->tracking_no, + 'tracking' => $this->tracking_english . ($this->remark_english ? " (" . $this->remark_english . ")" : ''), + 'tracking_time' => $this->tracking_time, + ]; + } +} diff --git a/app/Models/YDOrderTracking.php b/app/Models/YDOrderTracking.php index d265462e..a9f68de6 100644 --- a/app/Models/YDOrderTracking.php +++ b/app/Models/YDOrderTracking.php @@ -16,9 +16,11 @@ class YDOrderTracking extends Model 'tracking_no', 'package_id', 'tracking', + 'tracking_english', 'tracking_time', 'add_time', 'remark', + 'remark_english', 'eta', 'etd', ]; diff --git a/database/migrations/2025_03_19_132042_add_tracking_english_and_remark_english_to_yd_order_tracking_table.php b/database/migrations/2025_03_19_132042_add_tracking_english_and_remark_english_to_yd_order_tracking_table.php new file mode 100644 index 00000000..b728ce1e --- /dev/null +++ b/database/migrations/2025_03_19_132042_add_tracking_english_and_remark_english_to_yd_order_tracking_table.php @@ -0,0 +1,34 @@ +string('tracking_english')->nullable()->after('tracking'); + $table->text('remark_english')->nullable()->after('remark'); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('yd_order_tracking', function (Blueprint $table) { + $table->dropColumn(['tracking_english', 'remark_english']); + }); + } +} diff --git a/resources/assets/vue/components/orders/elements/PackageComponent.vue b/resources/assets/vue/components/orders/elements/PackageComponent.vue index 579ad87e..a502c3b1 100644 --- a/resources/assets/vue/components/orders/elements/PackageComponent.vue +++ b/resources/assets/vue/components/orders/elements/PackageComponent.vue @@ -22,7 +22,11 @@
Packinglist Reference
-