From 931de4471ca92528b0f7b691879452cf033503d6 Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Tue, 28 May 2024 16:52:35 +0800 Subject: [PATCH 1/8] Add feat unsold commodity notifications --- app/Console/Kernel.php | 6 +- app/Http/Controllers/SettingController.php | 97 +++++++++++++++++ .../WhatsappUnsoldCommodityNotification.php | 87 +++++++++++++++ app/Jobs/WhatsappUnsoldCommodityScanner.php | 55 ++++++++++ app/Setting.php | 19 ++++ bootstrap/app.php | 1 + ...024_05_27_093206_create_settings_table.php | 35 ++++++ ...093207_add_unsold_commodities_settings.php | 100 ++++++++++++++++++ routes/setting.php | 6 ++ 9 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/SettingController.php create mode 100644 app/Jobs/WhatsappUnsoldCommodityNotification.php create mode 100644 app/Jobs/WhatsappUnsoldCommodityScanner.php create mode 100644 app/Setting.php create mode 100644 database/migrations/2024_05_27_093206_create_settings_table.php create mode 100644 database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php create mode 100644 routes/setting.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index ad1e238..5c7d714 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -5,9 +5,7 @@ namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Laravel\Lumen\Console\Kernel as ConsoleKernel; -use App\Cawangan; -use App\Gadai; -use Carbon\Carbon; +use App\Jobs\WhatsappUnsoldCommodityScanner; class Kernel extends ConsoleKernel { @@ -34,5 +32,7 @@ class Kernel extends ConsoleKernel // $schedule->command('gadai:daily')->daily()->timezone('Asia/Kuala_Lumpur')->at('00:00'); + + $schedule->job(new WhatsappUnsoldCommodityScanner)->daily()->timezone('Asia/Kuala_Lumpur')->at('00:00'); } } diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php new file mode 100644 index 0000000..3f0e58f --- /dev/null +++ b/app/Http/Controllers/SettingController.php @@ -0,0 +1,97 @@ +get(); + + return response()->json($settings); + } + + public function updateUnsoldCommodityNotifications(Request $request) + { + $request_array = $request->input(); + + $general_inputs = array_filter( + $request_array, + function ($value, $key) { + return strpos($key, 'pic_') === false; + }, + ARRAY_FILTER_USE_BOTH + ); + + foreach ($general_inputs as $key => $value) { + Setting::where([ + ['group', 'unsold_commodity_notifications'], + ['key', $key] + ]) + ->first() + ->update(['value' => $value]); + } + + $pic_inputs = array_filter( + $request_array, + function ($value, $key) { + return Str::startsWith($key, 'pic_'); + }, + ARRAY_FILTER_USE_BOTH + ); + + $unique_pic_input = array_map(function ($array, $key) { + return $this->filterUniqueById($array, $key); + }, $pic_inputs, array_keys($pic_inputs)); + + $transformed_unique_pic_input = []; + + array_walk($unique_pic_input, function ($item) use (&$transformed_unique_pic_input) { + foreach ($item as $key => $value) { + $transformed_unique_pic_input[$key] = $value; + } + }); + + + foreach ($transformed_unique_pic_input as $key => $value) { + Setting::where([ + ['group', 'unsold_commodity_notifications'], + ['key', $key] + ]) + ->first() + ->update(['value' => json_encode($value)]); + } + + dispatch((new WhatsappUnsoldCommodityScanner())); + + return response()->json('success'); + } + + public function filterUniqueById($array, $key) + { + $uniqueIds = []; + $filteredArray = []; + + if($array !== [] ){ + foreach ($array as $item) { + if (!in_array($item['id'], $uniqueIds)) { + $uniqueIds[] = $item['id']; + $filteredArray[] = $item; + } + } + } + + return [ + $key => $filteredArray + ]; + } +} diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php new file mode 100644 index 0000000..2a8763a --- /dev/null +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -0,0 +1,87 @@ +where('group', 'unsold_commodity_notifications')->get(); + + $this->status = $settings->where('key', 'status')->first()->value; + + $this->start_time = $settings->where('key', 'start_time')->first()->value; + + $this->end_time = $settings->where('key', 'end_time')->first()->value; + + $this->message = $settings->where('key', 'message')->first()->value; + + $isKomoditiStillAvailable = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; + + $pic_key = 'pic_' . strtolower(Carbon::now()->englishDayOfWeek); + $pic = json_decode($settings->where('key', $pic_key)->first()->value); + + $phone_numbers = array_map(function ($p) { + if(isset($p->no_telefon)){ + return $p->no_telefon; + } + }, $pic); + + + if ($phone_numbers[0] === NULL) { + return; + } + + if ($this->status === '0') { + return; + } + + if (Carbon::parse($this->start_time) > Carbon::now()) { + return; + } + + if (Carbon::parse($this->end_time) < Carbon::now()) { + return; + } + + if (!$isKomoditiStillAvailable) { + return; + } + + foreach ($phone_numbers as $phone_number) { + Http::get(env('WABOT_API'), [ + 'number' => $phone_number, + 'type' => 'text', + 'message' => $this->message, + 'instance_id' => env('WABOT_INSTANCES_ID'), + 'access_token' => env('WABOT_TOKEN_KEYS') + ]); + } + + dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(5))); + } +} diff --git a/app/Jobs/WhatsappUnsoldCommodityScanner.php b/app/Jobs/WhatsappUnsoldCommodityScanner.php new file mode 100644 index 0000000..d64df49 --- /dev/null +++ b/app/Jobs/WhatsappUnsoldCommodityScanner.php @@ -0,0 +1,55 @@ +where('group', 'unsold_commodity_notifications')->get(); + + $this->status = $settings->where('key', 'status')->first()->value; + + $this->start_time = $settings->where('key', 'start_time')->first()->value; + + $this->end_time = $settings->where('key', 'end_time')->first()->value; + + $this->message = $settings->where('key', 'message')->first()->value; + + if ($this->status === '0') { + return; + } + + if (Carbon::parse($this->start_time) > Carbon::now()) { + return; + } + + if (Carbon::parse($this->end_time) < Carbon::now()) { + return; + } + + dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($this->start_time))); + } +} diff --git a/app/Setting.php b/app/Setting.php new file mode 100644 index 0000000..7bc5e32 --- /dev/null +++ b/app/Setting.php @@ -0,0 +1,19 @@ +router->group([ ], function ($router) { require __DIR__.'/../routes/web.php'; require __DIR__.'/../routes/report.php'; + require __DIR__.'/../routes/setting.php'; }); $app->middleware([ diff --git a/database/migrations/2024_05_27_093206_create_settings_table.php b/database/migrations/2024_05_27_093206_create_settings_table.php new file mode 100644 index 0000000..62b182b --- /dev/null +++ b/database/migrations/2024_05_27_093206_create_settings_table.php @@ -0,0 +1,35 @@ +id(); + $table->string('key')->unique(); + $table->text('value')->nullable(); + $table->string('group')->nullable(); + $table->text('description')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('settings'); + } +} diff --git a/database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php b/database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php new file mode 100644 index 0000000..70c983d --- /dev/null +++ b/database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php @@ -0,0 +1,100 @@ + 'status', + 'value' => 'true', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Turn on or turn off notification for unsold commodity notifications', + ], + [ + 'key' => 'start_time', + 'value' => '20:00', + 'group' => 'unsold_commodity_notifications', + 'description' => 'The time the notifications start', + ], + [ + 'key' => 'end_time', + 'value' => '23:00', + 'group' => 'unsold_commodity_notifications', + 'description' => 'The time the notifications end', + ], + [ + 'key' => 'message', + 'value' => 'Baki komoditi masih lagi berbaki dan belum habis dijual', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Turn on or turn off notification for unsold commodity notifications', + ], + [ + 'key' => 'pic_sunday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Sunday', + ], + [ + 'key' => 'pic_monday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Monday', + ], + [ + 'key' => 'pic_tuesday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Tuesday', + ], + [ + 'key' => 'pic_wednesday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Wednesday', + ], + [ + 'key' => 'pic_thursday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Thursday', + ], + [ + 'key' => 'pic_friday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Friday', + ], + [ + 'key' => 'pic_saturday', + 'value' => '', + 'group' => 'unsold_commodity_notifications', + 'description' => 'Person Incharge on Saturday', + ], + + ]; + + array_walk($data, function($setting){ + Setting::create($setting); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('settings'); + } +} diff --git a/routes/setting.php b/routes/setting.php new file mode 100644 index 0000000..e4e7a2f --- /dev/null +++ b/routes/setting.php @@ -0,0 +1,6 @@ +group(['prefix' => 'api/settings'], function () use ($router) { + $router->get('unsold-commodity-notifications', ['uses' => 'SettingController@getUnsoldCommodityNotifications']); + $router->post('unsold-commodity-notifications', ['uses' => 'SettingController@updateUnsoldCommodityNotifications']); +}); From 052f65307dd33a880565e2f20f5fe2a843888bb3 Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Fri, 31 May 2024 14:49:41 +0800 Subject: [PATCH 2/8] wip --- app/Http/Controllers/SettingController.php | 11 +++++- .../WhatsappUnsoldCommodityNotification.php | 20 ++++++++--- app/Jobs/WhatsappUnsoldCommodityScanner.php | 11 ++++-- .../2024_05_30_150239_create_job_statuses.php | 34 +++++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2024_05_30_150239_create_job_statuses.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 3f0e58f..4ede46e 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Jobs\WhatsappUnsoldCommodityNotification; use App\Jobs\WhatsappUnsoldCommodityScanner; +use App\JobStatus; use App\Setting; use Carbon\Carbon; use Illuminate\Http\Request; @@ -71,6 +72,7 @@ class SettingController extends Controller ->update(['value' => json_encode($value)]); } + $this->cancelPreviousNotificationJobs(); dispatch((new WhatsappUnsoldCommodityScanner())); return response()->json('success'); @@ -81,7 +83,7 @@ class SettingController extends Controller $uniqueIds = []; $filteredArray = []; - if($array !== [] ){ + if ($array !== []) { foreach ($array as $item) { if (!in_array($item['id'], $uniqueIds)) { $uniqueIds[] = $item['id']; @@ -94,4 +96,11 @@ class SettingController extends Controller $key => $filteredArray ]; } + + public function cancelPreviousNotificationJobs() + { + JobStatus::on('mysql7')->where('type', WhatsappUnsoldCommodityNotification::class)->update([ + 'status' => false + ]); + } } diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php index 2a8763a..04fcad7 100644 --- a/app/Jobs/WhatsappUnsoldCommodityNotification.php +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\JobStatus; use Illuminate\Support\Facades\Http; use App\Setting; use Carbon\Carbon; @@ -56,6 +57,10 @@ class WhatsappUnsoldCommodityNotification extends Job return; } + if(JobStatus::where('job_id', $this->job->getJobId()) === false){ + return; + } + if ($this->status === '0') { return; } @@ -68,9 +73,9 @@ class WhatsappUnsoldCommodityNotification extends Job return; } - if (!$isKomoditiStillAvailable) { - return; - } + // if (!$isKomoditiStillAvailable) { + // return; + // } foreach ($phone_numbers as $phone_number) { Http::get(env('WABOT_API'), [ @@ -82,6 +87,13 @@ class WhatsappUnsoldCommodityNotification extends Job ]); } - dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(5))); + $job_id = dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(1))); + Log::info($job_id); + + JobStatus::on('mysql7')->create([ + 'job_id' => $job_id, + 'type' => WhatsappUnsoldCommodityNotification::class, + 'status' => true, + ]); } } diff --git a/app/Jobs/WhatsappUnsoldCommodityScanner.php b/app/Jobs/WhatsappUnsoldCommodityScanner.php index d64df49..d7e184e 100644 --- a/app/Jobs/WhatsappUnsoldCommodityScanner.php +++ b/app/Jobs/WhatsappUnsoldCommodityScanner.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\JobStatus; use App\Setting; use Carbon\Carbon; @@ -28,7 +29,7 @@ class WhatsappUnsoldCommodityScanner extends Job */ public function handle() { - $settings = Setting::on()->where('group', 'unsold_commodity_notifications')->get(); + $settings = Setting::on('mysql7')->where('group', 'unsold_commodity_notifications')->get(); $this->status = $settings->where('key', 'status')->first()->value; @@ -50,6 +51,12 @@ class WhatsappUnsoldCommodityScanner extends Job return; } - dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($this->start_time))); + $job_id = dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($this->start_time))); + + JobStatus::on('mysql7')->create([ + 'job_id' => $job_id, + 'type' => WhatsappUnsoldCommodityNotification::class, + 'status' => true, + ]); } } diff --git a/database/migrations/2024_05_30_150239_create_job_statuses.php b/database/migrations/2024_05_30_150239_create_job_statuses.php new file mode 100644 index 0000000..57da3be --- /dev/null +++ b/database/migrations/2024_05_30_150239_create_job_statuses.php @@ -0,0 +1,34 @@ +id(); + $table->string('type'); + $table->unsignedBigInteger('job_id'); + $table->boolean('status'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('job_statuses'); + } +} From cbf6bd5f1facfddb1a6268e2e4cb3b57feb417fe Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Tue, 4 Jun 2024 18:48:06 +0800 Subject: [PATCH 3/8] Fix multiple notifications send to PIC at one time - fix by removing previous scheduled notifications job before updating the notification configurations --- app/Http/Controllers/SettingController.php | 32 +++++++++---- .../WhatsappUnsoldCommodityNotification.php | 47 +++++++------------ app/Jobs/WhatsappUnsoldCommodityScanner.php | 30 ++---------- config/app.php | 5 ++ config/database.php | 12 +++++ database/migrations/.vscode/settings.json | 3 ++ .../2024_05_30_150239_create_job_statuses.php | 34 -------------- 7 files changed, 65 insertions(+), 98 deletions(-) create mode 100644 config/app.php create mode 100644 database/migrations/.vscode/settings.json delete mode 100644 database/migrations/2024_05_30_150239_create_job_statuses.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 4ede46e..58a58bd 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -4,11 +4,10 @@ namespace App\Http\Controllers; use App\Jobs\WhatsappUnsoldCommodityNotification; use App\Jobs\WhatsappUnsoldCommodityScanner; -use App\JobStatus; use App\Setting; -use Carbon\Carbon; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -72,12 +71,14 @@ class SettingController extends Controller ->update(['value' => json_encode($value)]); } - $this->cancelPreviousNotificationJobs(); + $this->cancelPreviousCommodityNotificationsJobs(); + dispatch((new WhatsappUnsoldCommodityScanner())); return response()->json('success'); } + public function filterUniqueById($array, $key) { $uniqueIds = []; @@ -97,10 +98,25 @@ class SettingController extends Controller ]; } - public function cancelPreviousNotificationJobs() + + public function cancelPreviousCommodityNotificationsJobs() { - JobStatus::on('mysql7')->where('type', WhatsappUnsoldCommodityNotification::class)->update([ - 'status' => false - ]); + // flushed the fail job in queueu + Artisan::call('queue:flush'); + + $getClassNameString = function($className){ + $ola = explode("\\", $className); + return end($ola); + }; + + DB::connection('mysql7') + ->table('jobs') + ->where('payload', 'like', '%' . $getClassNameString(WhatsappUnsoldCommodityNotification::class) . '%') + ->delete(); + + DB::connection('mysql7') + ->table('jobs') + ->where('payload', 'like', '%' . $getClassNameString(WhatsappUnsoldCommodityScanner::class) . '%') + ->delete(); } } diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php index 04fcad7..cabd941 100644 --- a/app/Jobs/WhatsappUnsoldCommodityNotification.php +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -2,7 +2,6 @@ namespace App\Jobs; -use App\JobStatus; use Illuminate\Support\Facades\Http; use App\Setting; use Carbon\Carbon; @@ -31,69 +30,55 @@ class WhatsappUnsoldCommodityNotification extends Job */ public function handle() { + $settings = Setting::on('mysql7')->where('group', 'unsold_commodity_notifications')->get(); - - $this->status = $settings->where('key', 'status')->first()->value; - - $this->start_time = $settings->where('key', 'start_time')->first()->value; - - $this->end_time = $settings->where('key', 'end_time')->first()->value; - - $this->message = $settings->where('key', 'message')->first()->value; - + $status = $settings->where('key', 'status')->first()->value; + $start_time = $settings->where('key', 'start_time')->first()->value; + $end_time = $settings->where('key', 'end_time')->first()->value; + $message = $settings->where('key', 'message')->first()->value; $isKomoditiStillAvailable = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; $pic_key = 'pic_' . strtolower(Carbon::now()->englishDayOfWeek); $pic = json_decode($settings->where('key', $pic_key)->first()->value); $phone_numbers = array_map(function ($p) { - if(isset($p->no_telefon)){ + if (isset($p->no_telefon)) { return $p->no_telefon; } }, $pic); if ($phone_numbers[0] === NULL) { - return; + return false; } - if(JobStatus::where('job_id', $this->job->getJobId()) === false){ - return; + if ($status === '0') { + return false; } - if ($this->status === '0') { - return; + if (Carbon::parse($start_time) > Carbon::now()) { + return false; } - if (Carbon::parse($this->start_time) > Carbon::now()) { - return; - } - - if (Carbon::parse($this->end_time) < Carbon::now()) { - return; + if (Carbon::parse($end_time) < Carbon::now()) { + return false; } // if (!$isKomoditiStillAvailable) { - // return; + // return false; // } foreach ($phone_numbers as $phone_number) { Http::get(env('WABOT_API'), [ 'number' => $phone_number, 'type' => 'text', - 'message' => $this->message, + 'message' => $message, 'instance_id' => env('WABOT_INSTANCES_ID'), 'access_token' => env('WABOT_TOKEN_KEYS') ]); } - $job_id = dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(1))); - Log::info($job_id); + dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(5))); - JobStatus::on('mysql7')->create([ - 'job_id' => $job_id, - 'type' => WhatsappUnsoldCommodityNotification::class, - 'status' => true, - ]); } } diff --git a/app/Jobs/WhatsappUnsoldCommodityScanner.php b/app/Jobs/WhatsappUnsoldCommodityScanner.php index d7e184e..61e46de 100644 --- a/app/Jobs/WhatsappUnsoldCommodityScanner.php +++ b/app/Jobs/WhatsappUnsoldCommodityScanner.php @@ -2,7 +2,6 @@ namespace App\Jobs; -use App\JobStatus; use App\Setting; use Carbon\Carbon; @@ -10,7 +9,6 @@ class WhatsappUnsoldCommodityScanner extends Job { public $status; public $start_time; - public $end_time; public $message; /** @@ -30,33 +28,15 @@ class WhatsappUnsoldCommodityScanner extends Job public function handle() { $settings = Setting::on('mysql7')->where('group', 'unsold_commodity_notifications')->get(); + $status = $settings->where('key', 'status')->first()->value; + $start_time = $settings->where('key', 'start_time')->first()->value; - $this->status = $settings->where('key', 'status')->first()->value; - $this->start_time = $settings->where('key', 'start_time')->first()->value; - - $this->end_time = $settings->where('key', 'end_time')->first()->value; - - $this->message = $settings->where('key', 'message')->first()->value; - - if ($this->status === '0') { - return; + if ($status === '0') { + return false; } - if (Carbon::parse($this->start_time) > Carbon::now()) { - return; - } + dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($start_time))); - if (Carbon::parse($this->end_time) < Carbon::now()) { - return; - } - - $job_id = dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($this->start_time))); - - JobStatus::on('mysql7')->create([ - 'job_id' => $job_id, - 'type' => WhatsappUnsoldCommodityNotification::class, - 'status' => true, - ]); } } diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..ca53786 --- /dev/null +++ b/config/app.php @@ -0,0 +1,5 @@ + env('APP_URL', url('/')) +]; diff --git a/config/database.php b/config/database.php index f464311..71542a5 100644 --- a/config/database.php +++ b/config/database.php @@ -5,6 +5,18 @@ return [ 'default' => 'mysql7', 'migrations' => 'migrations', 'connections' => [ + 'mysql' => [ + 'driver' => 'mysql', + 'host' => env('DB_HOST_7'), + 'port' => env('DB_PORT_7'), + 'database' => env('DB_DATABASE_7'), + 'username' => env('DB_USERNAME_7'), + 'password' => env('DB_PASSWORD_7'), + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', + 'prefix' => '', + 'strict' => false, + ], 'lelong' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_LELONG'), diff --git a/database/migrations/.vscode/settings.json b/database/migrations/.vscode/settings.json new file mode 100644 index 0000000..ab4793e --- /dev/null +++ b/database/migrations/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "window.title": "[ ${rootNameShort} ] ➡️ ${dirty}${activeEditorMedium} ${separator}[Branch: test-simulator-nisha]" +} diff --git a/database/migrations/2024_05_30_150239_create_job_statuses.php b/database/migrations/2024_05_30_150239_create_job_statuses.php deleted file mode 100644 index 57da3be..0000000 --- a/database/migrations/2024_05_30_150239_create_job_statuses.php +++ /dev/null @@ -1,34 +0,0 @@ -id(); - $table->string('type'); - $table->unsignedBigInteger('job_id'); - $table->boolean('status'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('job_statuses'); - } -} From ab6ee95d643d7e7e541a2e431f838b3ff4671b2f Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Wed, 5 Jun 2024 16:04:39 +0800 Subject: [PATCH 4/8] Implement seeders instead of seeding using migrations, log whatasapp message --- app/Http/Controllers/SettingController.php | 25 ++++--- .../WhatsappUnsoldCommodityNotification.php | 24 +++++-- ...024_05_27_093206_create_settings_table.php | 4 ++ .../UnsoldCommodityNotificationPICSeeders.php | 70 +++++++++++++++++++ ...dCommodityNotificationSettingsSeeders.php} | 23 ++---- 5 files changed, 114 insertions(+), 32 deletions(-) create mode 100644 database/seeds/UnsoldCommodityNotificationPICSeeders.php rename database/{migrations/2024_05_27_093207_add_unsold_commodities_settings.php => seeds/UnsoldCommodityNotificationSettingsSeeders.php} (86%) diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 58a58bd..d743cea 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -104,19 +104,22 @@ class SettingController extends Controller // flushed the fail job in queueu Artisan::call('queue:flush'); - $getClassNameString = function($className){ - $ola = explode("\\", $className); - return end($ola); + $getClassNameString = function ($className) { + $name = explode("\\", $className); + return end($name); }; - DB::connection('mysql7') - ->table('jobs') - ->where('payload', 'like', '%' . $getClassNameString(WhatsappUnsoldCommodityNotification::class) . '%') - ->delete(); + $commodityNotificationClasses = [ + WhatsappUnsoldCommodityNotification::class, + WhatsappUnsoldCommodityScanner::class, + ]; - DB::connection('mysql7') - ->table('jobs') - ->where('payload', 'like', '%' . $getClassNameString(WhatsappUnsoldCommodityScanner::class) . '%') - ->delete(); + + foreach ($commodityNotificationClasses as $class) { + DB::connection('mysql7') + ->table('jobs') + ->where('payload', 'like', '%' . $getClassNameString($class) . '%') + ->delete(); + } } } diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php index cabd941..d218ae6 100644 --- a/app/Jobs/WhatsappUnsoldCommodityNotification.php +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\BlastWasap; use Illuminate\Support\Facades\Http; use App\Setting; use Carbon\Carbon; @@ -64,20 +65,35 @@ class WhatsappUnsoldCommodityNotification extends Job return false; } - // if (!$isKomoditiStillAvailable) { - // return false; - // } + if (!$isKomoditiStillAvailable) { + return false; + } foreach ($phone_numbers as $phone_number) { - Http::get(env('WABOT_API'), [ + $response = Http::get(env('WABOT_API'), [ 'number' => $phone_number, 'type' => 'text', 'message' => $message, 'instance_id' => env('WABOT_INSTANCES_ID'), 'access_token' => env('WABOT_TOKEN_KEYS') ]); + + + //insert log blast wasap + $logblastwasap = new BlastWasap(); + $logblastwasap->kodcaw = 'OPERASI'; + $logblastwasap->notelefon = $phone_number; + $logblastwasap->norujukan = 'Notifikasi Komoditi Tidak Terjual'; + $logblastwasap->status = $response; + $logblastwasap->created_at = Carbon::now(); + $logblastwasap->updated_at = Carbon::now(); + $logblastwasap->save(); + + Log::info("WABOT - Notifikasi Komoditi Tidak Terjual".$response); } + + dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(5))); } diff --git a/database/migrations/2024_05_27_093206_create_settings_table.php b/database/migrations/2024_05_27_093206_create_settings_table.php index 62b182b..c836094 100644 --- a/database/migrations/2024_05_27_093206_create_settings_table.php +++ b/database/migrations/2024_05_27_093206_create_settings_table.php @@ -21,6 +21,10 @@ class CreateSettingsTable extends Migration $table->text('description')->nullable(); $table->timestamps(); }); + + // Call the seeder + (new UnsoldCommodityNotificationSettingSeeders())->run(); + (new UnsoldCommodityNotificationPICSeeders())->run(); } /** diff --git a/database/seeds/UnsoldCommodityNotificationPICSeeders.php b/database/seeds/UnsoldCommodityNotificationPICSeeders.php new file mode 100644 index 0000000..35e45ea --- /dev/null +++ b/database/seeds/UnsoldCommodityNotificationPICSeeders.php @@ -0,0 +1,70 @@ + [ + [ + 'id' => 366, // nurasiah@pkb.net.my + 'no_telefon' => '0123456789', + ] + ], + 'pic_monday' => [ + [ + 'id' => 343, // syada@pkb.net.my + 'no_telefon' => '0139403344', + ], + [ + 'id' => 54, // shahmin@pkb.net.my + 'no_telefon' => '0196438873', + ] + ], + 'pic_tuesday' => [ + [ + 'id' => 55, // manita@pkb.net.my + 'no_telefon' => '0179545432', + ] + ], + 'pic_wednesday' => [ + [ + 'id' => 52, // izzudin@pkb.net.my + 'no_telefon' => '0199011095', + ] + ], + 'pic_thursday' => [ + [ + 'id' => 53, // norosmini@pkb.net.my + 'no_telefon' => '0129493588', + ], + [ + 'id' => 56, // rozarina@pkb.net.my + 'no_telefon' => '0129616201', + ], + ], + 'pic_friday' => [[]], + 'pic_saturday' => [[]], + ]; + + $transformed_data = array_map(function($pic){ + return json_encode($pic); + }, $data_pic); + + $outputs = array_combine(array_keys($data_pic), $transformed_data); + + foreach ($outputs as $key => $data) { + Setting::where('group', 'unsold_commodity_notifications') + ->where('key', $key) + ->update(['value' => $data]); + } + } +} diff --git a/database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php b/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php similarity index 86% rename from database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php rename to database/seeds/UnsoldCommodityNotificationSettingsSeeders.php index 70c983d..f284669 100644 --- a/database/migrations/2024_05_27_093207_add_unsold_commodities_settings.php +++ b/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php @@ -1,22 +1,21 @@ 'status', - 'value' => 'true', + 'value' => '1', 'group' => 'unsold_commodity_notifications', 'description' => 'Turn on or turn off notification for unsold commodity notifications', ], @@ -83,18 +82,8 @@ class AddUnsoldCommoditiesSettings extends Migration ]; - array_walk($data, function($setting){ + array_walk($data, function ($setting) { Setting::create($setting); }); } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('settings'); - } } From 4f96b450037d8f14f048153ae475433812174514 Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Wed, 5 Jun 2024 16:47:59 +0800 Subject: [PATCH 5/8] Fix check commodity is sold or not --- app/Jobs/WhatsappUnsoldCommodityNotification.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php index d218ae6..60ee602 100644 --- a/app/Jobs/WhatsappUnsoldCommodityNotification.php +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -37,7 +37,7 @@ class WhatsappUnsoldCommodityNotification extends Job $start_time = $settings->where('key', 'start_time')->first()->value; $end_time = $settings->where('key', 'end_time')->first()->value; $message = $settings->where('key', 'message')->first()->value; - $isKomoditiStillAvailable = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; + $isKomoditiStillSold = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; $pic_key = 'pic_' . strtolower(Carbon::now()->englishDayOfWeek); $pic = json_decode($settings->where('key', $pic_key)->first()->value); @@ -65,7 +65,7 @@ class WhatsappUnsoldCommodityNotification extends Job return false; } - if (!$isKomoditiStillAvailable) { + if ($isKomoditiStillSold) { return false; } From 3686fb93de9563f4e24ca91a93ea2d94f43e13ba Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Mon, 10 Jun 2024 17:09:17 +0800 Subject: [PATCH 6/8] Empty pic seeders --- .../UnsoldCommodityNotificationPICSeeders.php | 43 +++---------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/database/seeds/UnsoldCommodityNotificationPICSeeders.php b/database/seeds/UnsoldCommodityNotificationPICSeeders.php index 35e45ea..3092409 100644 --- a/database/seeds/UnsoldCommodityNotificationPICSeeders.php +++ b/database/seeds/UnsoldCommodityNotificationPICSeeders.php @@ -13,44 +13,11 @@ class UnsoldCommodityNotificationPICSeeders extends Seeder public function run() { $data_pic = [ - 'pic_sunday' => [ - [ - 'id' => 366, // nurasiah@pkb.net.my - 'no_telefon' => '0123456789', - ] - ], - 'pic_monday' => [ - [ - 'id' => 343, // syada@pkb.net.my - 'no_telefon' => '0139403344', - ], - [ - 'id' => 54, // shahmin@pkb.net.my - 'no_telefon' => '0196438873', - ] - ], - 'pic_tuesday' => [ - [ - 'id' => 55, // manita@pkb.net.my - 'no_telefon' => '0179545432', - ] - ], - 'pic_wednesday' => [ - [ - 'id' => 52, // izzudin@pkb.net.my - 'no_telefon' => '0199011095', - ] - ], - 'pic_thursday' => [ - [ - 'id' => 53, // norosmini@pkb.net.my - 'no_telefon' => '0129493588', - ], - [ - 'id' => 56, // rozarina@pkb.net.my - 'no_telefon' => '0129616201', - ], - ], + 'pic_sunday' => [[]], + 'pic_monday' => [[]], + 'pic_tuesday' => [[]], + 'pic_wednesday' => [[]], + 'pic_thursday' => [[]], 'pic_friday' => [[]], 'pic_saturday' => [[]], ]; From 119f6d642800f5f14195cfec41a082ce795a6d67 Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Mon, 10 Jun 2024 18:32:02 +0800 Subject: [PATCH 7/8] Codebase update - Remove default pic assignments for unsold commodity notifications - Check wabot credential complete first before notification blast, if incomplete no notification be sent - Change migration column order for settings table, column group first - Resolve error of not showing select after updating any PIC for selected day --- app/Http/Controllers/SettingController.php | 5 + .../WhatsappUnsoldCommodityNotification.php | 16 +- ...024_05_27_093206_create_settings_table.php | 21 +-- .../arrahn_master_db_202405160953.json | 139 ++++++++++++++++++ .../UnsoldCommodityNotificationPICSeeders.php | 37 ----- ...ldCommodityNotificationSettingsSeeders.php | 16 +- 6 files changed, 176 insertions(+), 58 deletions(-) create mode 100644 database/migrations/arrahn_master_db_202405160953.json delete mode 100644 database/seeds/UnsoldCommodityNotificationPICSeeders.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index d743cea..bf9476a 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -57,6 +57,11 @@ class SettingController extends Controller array_walk($unique_pic_input, function ($item) use (&$transformed_unique_pic_input) { foreach ($item as $key => $value) { + + if(count($value) === 0){ + $value = [new \stdClass()]; + } + $transformed_unique_pic_input[$key] = $value; } }); diff --git a/app/Jobs/WhatsappUnsoldCommodityNotification.php b/app/Jobs/WhatsappUnsoldCommodityNotification.php index 60ee602..fe0dd51 100644 --- a/app/Jobs/WhatsappUnsoldCommodityNotification.php +++ b/app/Jobs/WhatsappUnsoldCommodityNotification.php @@ -37,7 +37,8 @@ class WhatsappUnsoldCommodityNotification extends Job $start_time = $settings->where('key', 'start_time')->first()->value; $end_time = $settings->where('key', 'end_time')->first()->value; $message = $settings->where('key', 'message')->first()->value; - $isKomoditiStillSold = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; + $isAllKomoditiSold = KomuditiPurchase::on('mysql7')->latest()->first()->unit_komuditi === 0; + $isWabotCredentialNotComplete = env('WABOT_API') === null || env('WABOT_INSTANCES_ID') === null || env('WABOT_TOKEN_KEYS') === null; $pic_key = 'pic_' . strtolower(Carbon::now()->englishDayOfWeek); $pic = json_decode($settings->where('key', $pic_key)->first()->value); @@ -48,12 +49,18 @@ class WhatsappUnsoldCommodityNotification extends Job } }, $pic); + if ($isWabotCredentialNotComplete) { + Log::error('Wabot credential not complete'); + return false; + } if ($phone_numbers[0] === NULL) { + Log::error('No PIC phone numbers detected'); return false; } if ($status === '0') { + Log::info('Unsold commodity notifications are turned off, no notification will be sent'); return false; } @@ -65,10 +72,12 @@ class WhatsappUnsoldCommodityNotification extends Job return false; } - if ($isKomoditiStillSold) { + if ($isAllKomoditiSold) { + Log::info('All komoditi is sold'); return false; } + foreach ($phone_numbers as $phone_number) { $response = Http::get(env('WABOT_API'), [ 'number' => $phone_number, @@ -89,12 +98,11 @@ class WhatsappUnsoldCommodityNotification extends Job $logblastwasap->updated_at = Carbon::now(); $logblastwasap->save(); - Log::info("WABOT - Notifikasi Komoditi Tidak Terjual".$response); + Log::info("WABOT - Notifikasi Komoditi Tidak Terjual" . $response); } dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::now()->addMinutes(5))); - } } diff --git a/database/migrations/2024_05_27_093206_create_settings_table.php b/database/migrations/2024_05_27_093206_create_settings_table.php index c836094..f1edbaa 100644 --- a/database/migrations/2024_05_27_093206_create_settings_table.php +++ b/database/migrations/2024_05_27_093206_create_settings_table.php @@ -13,18 +13,19 @@ class CreateSettingsTable extends Migration */ public function up() { - Schema::create('settings', function (Blueprint $table) { - $table->id(); - $table->string('key')->unique(); - $table->text('value')->nullable(); - $table->string('group')->nullable(); - $table->text('description')->nullable(); - $table->timestamps(); - }); + if (!Schema::hasTable('settings')) { + Schema::create('settings', function (Blueprint $table) { + $table->id(); + $table->string('group')->nullable(); + $table->string('key')->unique(); + $table->text('value')->nullable(); + $table->text('description')->nullable(); + $table->timestamps(); + }); + } // Call the seeder - (new UnsoldCommodityNotificationSettingSeeders())->run(); - (new UnsoldCommodityNotificationPICSeeders())->run(); + (new UnsoldCommodityNotificationSettingSeeders())->run(); } /** diff --git a/database/migrations/arrahn_master_db_202405160953.json b/database/migrations/arrahn_master_db_202405160953.json new file mode 100644 index 0000000..ab3e6ca --- /dev/null +++ b/database/migrations/arrahn_master_db_202405160953.json @@ -0,0 +1,139 @@ +{ +"arrahn_master_db": [ + { + "details_caw" : "Kota Bharu 2", + "kodcaw" : "KB2" + }, + { + "details_caw" : "Wakaf Che Yeh", + "kodcaw" : "WCY" + }, + { + "details_caw" : "1 Stop", + "kodcaw" : "1STOP" + }, + { + "details_caw" : "Jelawat", + "kodcaw" : "020301" + }, + { + "details_caw" : "Wakaf Bharu", + "kodcaw" : "WB" + }, + { + "details_caw" : "Kok Lanas", + "kodcaw" : "ALS" + }, + { + "details_caw" : "Pasir Puteh", + "kodcaw" : "020306" + }, + { + "details_caw" : "Machang", + "kodcaw" : "ARM" + }, + { + "details_caw" : "Pasir Mas", + "kodcaw" : "APM" + }, + { + "details_caw" : "Gua Musang", + "kodcaw" : "010311" + }, + { + "details_caw" : "Guchil", + "kodcaw" : "GC" + }, + { + "details_caw" : "Jeli", + "kodcaw" : "JLI" + }, + { + "details_caw" : "Rantau Panjang", + "kodcaw" : "ARP" + }, + { + "details_caw" : "Kuantan", + "kodcaw" : "010621" + }, + { + "details_caw" : "Pasir Gudang", + "kodcaw" : "010136" + }, + { + "details_caw" : "Skudai", + "kodcaw" : "011235" + }, + { + "details_caw" : "Putatan", + "kodcaw" : "011227" + }, + { + "details_caw" : "Bentong", + "kodcaw" : "010620" + }, + { + "details_caw" : "Raub", + "kodcaw" : "010617" + }, + { + "details_caw" : "Kangar", + "kodcaw" : "010915" + }, + { + "details_caw" : "Sandakan", + "kodcaw" : "011228" + }, + { + "details_caw" : "Sungai Petani", + "kodcaw" : "010219" + }, + { + "details_caw" : "Tawau", + "kodcaw" : "011229" + }, + { + "details_caw" : "Api-Api", + "kodcaw" : "011230" + }, + { + "details_caw" : "Kajang", + "kodcaw" : "011013" + }, + { + "details_caw" : "Raja Laut", + "kodcaw" : "011412" + }, + { + "details_caw" : "Beaufort", + "kodcaw" : "011231" + }, + { + "details_caw" : "Kota Belud", + "kodcaw" : "011232" + }, + { + "details_caw" : "Tuaran", + "kodcaw" : "011234" + }, + { + "details_caw" : "Keningau", + "kodcaw" : "011233" + }, + { + "details_caw" : "Tanah Merah", + "kodcaw" : "020303" + }, + { + "details_caw" : "Temerloh", + "kodcaw" : "010618" + }, + { + "details_caw" : "Semporna", + "kodcaw" : "011237" + }, + { + "details_caw" : "Kota Bharu 1", + "kodcaw" : "KB1" + } +]} diff --git a/database/seeds/UnsoldCommodityNotificationPICSeeders.php b/database/seeds/UnsoldCommodityNotificationPICSeeders.php deleted file mode 100644 index 3092409..0000000 --- a/database/seeds/UnsoldCommodityNotificationPICSeeders.php +++ /dev/null @@ -1,37 +0,0 @@ - [[]], - 'pic_monday' => [[]], - 'pic_tuesday' => [[]], - 'pic_wednesday' => [[]], - 'pic_thursday' => [[]], - 'pic_friday' => [[]], - 'pic_saturday' => [[]], - ]; - - $transformed_data = array_map(function($pic){ - return json_encode($pic); - }, $data_pic); - - $outputs = array_combine(array_keys($data_pic), $transformed_data); - - foreach ($outputs as $key => $data) { - Setting::where('group', 'unsold_commodity_notifications') - ->where('key', $key) - ->update(['value' => $data]); - } - } -} diff --git a/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php b/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php index f284669..9bfab95 100644 --- a/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php +++ b/database/seeds/UnsoldCommodityNotificationSettingsSeeders.php @@ -12,6 +12,8 @@ class UnsoldCommodityNotificationSettingSeeders extends Seeder */ public function run() { + Setting::where('group', 'unsold_commodity_notifications')->each(fn($x) => $x->delete()); + $data = [ [ 'key' => 'status', @@ -39,43 +41,43 @@ class UnsoldCommodityNotificationSettingSeeders extends Seeder ], [ 'key' => 'pic_sunday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Sunday', ], [ 'key' => 'pic_monday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Monday', ], [ 'key' => 'pic_tuesday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Tuesday', ], [ 'key' => 'pic_wednesday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Wednesday', ], [ 'key' => 'pic_thursday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Thursday', ], [ 'key' => 'pic_friday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Friday', ], [ 'key' => 'pic_saturday', - 'value' => '', + 'value' => '[{}]', 'group' => 'unsold_commodity_notifications', 'description' => 'Person Incharge on Saturday', ], From 3b223bf4c42777c293ad909d34370e8fe55c047a Mon Sep 17 00:00:00 2001 From: Afiq Hamzah Date: Tue, 11 Jun 2024 08:54:21 +0800 Subject: [PATCH 8/8] Remove stray vscode setting config --- database/migrations/.vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 database/migrations/.vscode/settings.json diff --git a/database/migrations/.vscode/settings.json b/database/migrations/.vscode/settings.json deleted file mode 100644 index ab4793e..0000000 --- a/database/migrations/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "window.title": "[ ${rootNameShort} ] ➡️ ${dirty}${activeEditorMedium} ${separator}[Branch: test-simulator-nisha]" -}