Merged in afiqhamzah/feat/unsold-commodity-notification (pull request #173)

Afiqhamzah/feat/unsold commodity notification
This commit is contained in:
Afiq Hamzah
2024-06-11 03:44:55 +00:00
12 changed files with 596 additions and 3 deletions
+3 -3
View File
@@ -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');
}
}
+130
View File
@@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers;
use App\Jobs\WhatsappUnsoldCommodityNotification;
use App\Jobs\WhatsappUnsoldCommodityScanner;
use App\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class SettingController extends Controller
{
public function getUnsoldCommodityNotifications()
{
$settings = Setting::where('group', 'unsold_commodity_notifications')->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) {
if(count($value) === 0){
$value = [new \stdClass()];
}
$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)]);
}
$this->cancelPreviousCommodityNotificationsJobs();
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
];
}
public function cancelPreviousCommodityNotificationsJobs()
{
// flushed the fail job in queueu
Artisan::call('queue:flush');
$getClassNameString = function ($className) {
$name = explode("\\", $className);
return end($name);
};
$commodityNotificationClasses = [
WhatsappUnsoldCommodityNotification::class,
WhatsappUnsoldCommodityScanner::class,
];
foreach ($commodityNotificationClasses as $class) {
DB::connection('mysql7')
->table('jobs')
->where('payload', 'like', '%' . $getClassNameString($class) . '%')
->delete();
}
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Jobs;
use App\BlastWasap;
use Illuminate\Support\Facades\Http;
use App\Setting;
use Carbon\Carbon;
use App\KomuditiPurchase;
use Illuminate\Support\Facades\Log;
class WhatsappUnsoldCommodityNotification extends Job
{
public $status;
public $start_time;
public $end_time;
public $message;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
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;
$end_time = $settings->where('key', 'end_time')->first()->value;
$message = $settings->where('key', 'message')->first()->value;
$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);
$phone_numbers = array_map(function ($p) {
if (isset($p->no_telefon)) {
return $p->no_telefon;
}
}, $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;
}
if (Carbon::parse($start_time) > Carbon::now()) {
return false;
}
if (Carbon::parse($end_time) < Carbon::now()) {
return false;
}
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,
'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)));
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Jobs;
use App\Setting;
use Carbon\Carbon;
class WhatsappUnsoldCommodityScanner extends Job
{
public $status;
public $start_time;
public $message;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
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;
if ($status === '0') {
return false;
}
dispatch((new WhatsappUnsoldCommodityNotification($this->message))->delay(Carbon::parse($start_time)));
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $fillable = [
'key',
'value',
'group',
'description',
];
}
+1
View File
@@ -114,6 +114,7 @@ $app->router->group([
], function ($router) {
require __DIR__.'/../routes/web.php';
require __DIR__.'/../routes/report.php';
require __DIR__.'/../routes/setting.php';
});
$app->middleware([
+5
View File
@@ -0,0 +1,5 @@
<?php
return [
'url' => env('APP_URL', url('/'))
];
+12
View File
@@ -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'),
@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
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();
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('settings');
}
}
@@ -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"
}
]}
@@ -0,0 +1,91 @@
<?php
use App\Setting;
use Illuminate\Database\Seeder;
class UnsoldCommodityNotificationSettingSeeders extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Setting::where('group', 'unsold_commodity_notifications')->each(fn($x) => $x->delete());
$data = [
[
'key' => 'status',
'value' => '1',
'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);
});
}
}
+6
View File
@@ -0,0 +1,6 @@
<?php
$router->group(['prefix' => 'api/settings'], function () use ($router) {
$router->get('unsold-commodity-notifications', ['uses' => 'SettingController@getUnsoldCommodityNotifications']);
$router->post('unsold-commodity-notifications', ['uses' => 'SettingController@updateUnsoldCommodityNotifications']);
});