diff --git a/init.php b/init.php
index 1bcd73f8..16e7bd36 100644
--- a/init.php
+++ b/init.php
@@ -50,6 +50,7 @@ if (!file_exists($root_path .  File::pathFixer('system/orm.php'))) {
     die($root_path . "orm.php file not found");
 }
 
+$DEVICE_PATH = $root_path . File::pathFixer('system/devices');
 $UPLOAD_PATH = $root_path . File::pathFixer('system/uploads');
 $CACHE_PATH = $root_path . File::pathFixer('system/cache');
 $PAGES_PATH = $root_path . File::pathFixer('pages');
@@ -332,7 +333,7 @@ function displayMaintenanceMessage(): void
     $date = $config['maintenance_date'];
     if ($date){
         $ui->assign('date', $date);
-    }  
+    }
     http_response_code(503);
     $ui->assign('companyName', $config['CompanyName']);
     $ui->display('maintenance.tpl');
diff --git a/system/autoload/Package.php b/system/autoload/Package.php
index aa2fda95..8a98226d 100644
--- a/system/autoload/Package.php
+++ b/system/autoload/Package.php
@@ -20,7 +20,7 @@ class Package
      */
     public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel, $note = '')
     {
-        global $config, $admin, $c, $p, $b, $t, $d, $zero, $trx;
+        global $config, $admin, $c, $p, $b, $t, $d, $zero, $trx, $DEVICE_PATH;
         $date_now = date("Y-m-d H:i:s");
         $date_only = date("Y-m-d");
         $time_only = date("H:i:s");
@@ -162,8 +162,6 @@ class Package
 
         run_hook("recharge_user");
 
-
-        $mikrotik = Mikrotik::info($router_name);
         if ($p['validity_unit'] == 'Months') {
             $date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' month'));
         } else if ($p['validity_unit'] == 'Period') {
@@ -192,412 +190,210 @@ class Package
             $time = $datetime[1];
         }
         $isChangePlan = false;
-        if ($p['type'] == 'Hotspot') {
-            if ($b) {
-                if ($plan_id != $b['plan_id']) {
-                    $isChangePlan = true;
-                }
-                if ($config['extend_expiry'] != 'no') {
-                    if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
-                        // if it same internet plan, expired will extend
-                        if ($p['validity_unit'] == 'Months') {
-                            $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
-                            $time = $b['time'];
-                        } else if ($p['validity_unit'] == 'Period') {
-                            $date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
-                            $time = date("23:59:00");
-                        } else if ($p['validity_unit'] == 'Days') {
-                            $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
-                            $time = $b['time'];
-                        } else if ($p['validity_unit'] == 'Hrs') {
-                            $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours')));
-                            $date_exp = $datetime[0];
-                            $time = $datetime[1];
-                        } else if ($p['validity_unit'] == 'Mins') {
-                            $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' minutes')));
-                            $date_exp = $datetime[0];
-                            $time = $datetime[1];
-                        }
-                    }
-                }
-                if ($isChangePlan || $b['status'] == 'off') {
-                    if ($p['is_radius']) {
-                        Radius::customerAddPlan($c, $p, "$date_exp $time");
-                    } else {
-                        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                        Mikrotik::removeHotspotUser($client, $c['username']);
-                        Mikrotik::removeHotspotActiveUser($client, $c['username']);
-                        Mikrotik::addHotspotUser($client, $p, $c);
-                    }
-                }
 
-                $b->customer_id = $id_customer;
-                $b->username = $c['username'];
-                $b->plan_id = $plan_id;
-                $b->namebp = $p['name_plan'];
-                $b->recharged_on = $date_only;
-                $b->recharged_time = $time_only;
-                $b->expiration = $date_exp;
-                $b->time = $time;
-                $b->status = "on";
-                $b->method = "$gateway - $channel";
-                $b->routers = $router_name;
-                $b->type = "Hotspot";
-                if ($admin) {
-                    $b->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $b->admin_id = '0';
-                }
-                $b->save();
-
-                // insert table transactions
-                $t = ORM::for_table('tbl_transactions')->create();
-                $t->invoice = $inv = "INV-" . Package::_raid();
-                $t->username = $c['username'];
-                $t->plan_name = $p['name_plan'];
-                if ($p['validity_unit'] == 'Period') {
-                    // Postpaid price from field
-                    $add_inv = User::getAttribute("Invoice", $id_customer);
-                    if (empty($add_inv) or $add_inv == 0) {
-                        $t->price = $p['price'] + $add_cost;
-                    } else {
-                        $t->price = $add_inv + $add_cost;
-                    }
-                } else {
-                    $t->price = $p['price'] + $add_cost;
-                }
-                $t->recharged_on = $date_only;
-                $t->recharged_time = $time_only;
-                $t->expiration = $date_exp;
-                $t->time = $time;
-                $t->method = "$gateway - $channel";
-                $t->routers = $router_name;
-                $t->note = $note;
-                $t->type = "Hotspot";
-                if ($admin) {
-                    $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $t->admin_id = '0';
-                }
-                $t->save();
-
-                if ($p['validity_unit'] == 'Period') {
-                    // insert price to fields for invoice next month
-                    $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
-                    if (!$fl) {
-                        $fl = ORM::for_table('tbl_customers_fields')->create();
-                        $fl->customer_id = $c['id'];
-                        $fl->field_name = 'Invoice';
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    } else {
-                        $fl->customer_id = $c['id'];
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    }
-                }
-
-
-                Message::sendTelegram("#u$c[username] $c[fullname] #recharge #Hotspot \n" . $p['name_plan'] .
-                    "\nRouter: " . $router_name .
-                    "\nGateway: " . $gateway .
-                    "\nChannel: " . $channel .
-                    "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
-                    "\nNote:\n" . $note);
-            } else {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p, "$date_exp $time");
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removeHotspotUser($client, $c['username']);
-                    Mikrotik::removeHotspotActiveUser($client, $c['username']);
-                    Mikrotik::addHotspotUser($client, $p, $c);
-                }
-
-                $d = ORM::for_table('tbl_user_recharges')->create();
-                $d->customer_id = $id_customer;
-                $d->username = $c['username'];
-                $d->plan_id = $plan_id;
-                $d->namebp = $p['name_plan'];
-                $d->recharged_on = $date_only;
-                $d->recharged_time = $time_only;
-                $d->expiration = $date_exp;
-                $d->time = $time;
-                $d->status = "on";
-                $d->method = "$gateway - $channel";
-                $d->routers = $router_name;
-                $d->type = "Hotspot";
-                if ($admin) {
-                    $d->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $d->admin_id = '0';
-                }
-                $d->save();
-
-                // insert table transactions
-                $t = ORM::for_table('tbl_transactions')->create();
-                $t->invoice = $inv = "INV-" . Package::_raid();
-                $t->username = $c['username'];
-                $t->plan_name = $p['name_plan'];
-                if ($p['validity_unit'] == 'Period') {
-                    // Postpaid price always zero for first time
-                    $t->price = 0 + $add_cost;
-                } else {
-                    $t->price = $p['price'] + $add_cost;
-                }
-                $t->recharged_on = $date_only;
-                $t->recharged_time = $time_only;
-                $t->expiration = $date_exp;
-                $t->time = $time;
-                $t->method = "$gateway - $channel";
-                $t->routers = $router_name;
-                $t->note = $note;
-                $t->type = "Hotspot";
-                if ($admin) {
-                    $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $t->admin_id = '0';
-                }
-                $t->save();
-
-                if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
-                    // insert price to fields for invoice next month
-                    $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
-                    if (!$fl) {
-                        $fl = ORM::for_table('tbl_customers_fields')->create();
-                        $fl->customer_id = $c['id'];
-                        $fl->field_name = 'Invoice';
-                        // Calculating Price
-                        $sd = new DateTime("$date_only");
-                        $ed = new DateTime("$date_exp");
-                        $td = $ed->diff($sd);
-                        $fd = $td->format("%a");
-                        $gi = ($p['price'] / (30 * $p['validity'])) * $fd;
-                        if ($gi > $p['price']) {
-                            $fl->field_value = $p['price'];
-                        } else {
-                            $fl->field_value = $gi;
-                        }
-                        $fl->save();
-                    } else {
-                        $fl->customer_id = $c['id'];
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    }
-                }
-
-                Message::sendTelegram("#u$c[username] $c[fullname] #buy #Hotspot \n" . $p['name_plan'] .
-                    "\nRouter: " . $router_name .
-                    "\nGateway: " . $gateway .
-                    "\nChannel: " . $channel .
-                    "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
-                    "\nNote:\n" . $note);
+        if ($b) {
+            // plan exists
+            if ($plan_id != $b['plan_id']) {
+                $isChangePlan = true;
             }
+            if ($config['extend_expiry'] != 'no') {
+                if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
+                    // if it same internet plan, expired will extend
+                    if ($p['validity_unit'] == 'Months') {
+                        $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
+                        $time = $b['time'];
+                    } else if ($p['validity_unit'] == 'Period') {
+                        $date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
+                        $time = date("23:59:00");
+                    } else if ($p['validity_unit'] == 'Days') {
+                        $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
+                        $time = $b['time'];
+                    } else if ($p['validity_unit'] == 'Hrs') {
+                        $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours')));
+                        $date_exp = $datetime[0];
+                        $time = $datetime[1];
+                    } else if ($p['validity_unit'] == 'Mins') {
+                        $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' minutes')));
+                        $date_exp = $datetime[0];
+                        $time = $datetime[1];
+                    }
+                }
+            }
+
+            if ($isChangePlan || $b['status'] == 'off') {
+                $dvc = $DEVICE_PATH . DIRECTORY_SEPARATOR . $p['device'] . '.php';
+                if (file_exists($dvc)) {
+                    include $dvc;
+                    new $p['device']->connect_customer($c, $p);
+                } else {
+                    new Exception(Lang::T("Devices Not Found"));
+                }
+            }
+
+            $b->customer_id = $id_customer;
+            $b->username = $c['username'];
+            $b->plan_id = $plan_id;
+            $b->namebp = $p['name_plan'];
+            $b->recharged_on = $date_only;
+            $b->recharged_time = $time_only;
+            $b->expiration = $date_exp;
+            $b->time = $time;
+            $b->status = "on";
+            $b->method = "$gateway - $channel";
+            $b->routers = $router_name;
+            $b->type = $p['type'];
+            if ($admin) {
+                $b->admin_id = ($admin['id']) ? $admin['id'] : '0';
+            } else {
+                $b->admin_id = '0';
+            }
+            $b->save();
+
+            // insert table transactions
+            $t = ORM::for_table('tbl_transactions')->create();
+            $t->invoice = $inv = "INV-" . Package::_raid();
+            $t->username = $c['username'];
+            $t->plan_name = $p['name_plan'];
+            if ($p['validity_unit'] == 'Period') {
+                // Postpaid price from field
+                $add_inv = User::getAttribute("Invoice", $id_customer);
+                if (empty($add_inv) or $add_inv == 0) {
+                    $t->price = $p['price'] + $add_cost;
+                } else {
+                    $t->price = $add_inv + $add_cost;
+                }
+            } else {
+                $t->price = $p['price'] + $add_cost;
+            }
+            $t->recharged_on = $date_only;
+            $t->recharged_time = $time_only;
+            $t->expiration = $date_exp;
+            $t->time = $time;
+            $t->method = "$gateway - $channel";
+            $t->routers = $router_name;
+            $t->note = $note;
+            $t->type = $p['type'];
+            if ($admin) {
+                $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
+            } else {
+                $t->admin_id = '0';
+            }
+            $t->save();
+
+            if ($p['validity_unit'] == 'Period') {
+                // insert price to fields for invoice next month
+                $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
+                if (!$fl) {
+                    $fl = ORM::for_table('tbl_customers_fields')->create();
+                    $fl->customer_id = $c['id'];
+                    $fl->field_name = 'Invoice';
+                    $fl->field_value = $p['price'];
+                    $fl->save();
+                } else {
+                    $fl->customer_id = $c['id'];
+                    $fl->field_value = $p['price'];
+                    $fl->save();
+                }
+            }
+
+            Message::sendTelegram("#u$c[username] $c[fullname] #recharge #$p[type] \n" . $p['name_plan'] .
+                "\nRouter: " . $router_name .
+                "\nGateway: " . $gateway .
+                "\nChannel: " . $channel .
+                "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
+                "\nNote:\n" . $note);
         } else {
-
-            if ($b) {
-                if ($plan_id != $b['plan_id']) {
-                    $isChangePlan = true;
-                }
-                if ($config['extend_expiry'] != 'no') {
-                    if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
-                        // if it same internet plan, expired will extend
-                        if ($p['validity_unit'] == 'Months') {
-                            $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
-                            $time = $b['time'];
-                        } else if ($p['validity_unit'] == 'Period') {
-                            $date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
-                            $time = date("23:59:00");
-                        } else if ($p['validity_unit'] == 'Days') {
-                            $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
-                            $time = $b['time'];
-                        } else if ($p['validity_unit'] == 'Hrs') {
-                            $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours')));
-                            $date_exp = $datetime[0];
-                            $time = $datetime[1];
-                        } else if ($p['validity_unit'] == 'Mins') {
-                            $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' minutes')));
-                            $date_exp = $datetime[0];
-                            $time = $datetime[1];
-                        }
-                    }
-                }
-
-                if ($isChangePlan || $b['status'] == 'off') {
-                    if ($p['is_radius']) {
-                        Radius::customerAddPlan($c, $p, "$date_exp $time");
-                    } else {
-                        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                        Mikrotik::removePpoeUser($client, $c['username']);
-                        Mikrotik::removePpoeActive($client, $c['username']);
-                        Mikrotik::addPpoeUser($client, $p, $c);
-                    }
-                }
-
-                $b->customer_id = $id_customer;
-                $b->username = $c['username'];
-                $b->plan_id = $plan_id;
-                $b->namebp = $p['name_plan'];
-                $b->recharged_on = $date_only;
-                $b->recharged_time = $time_only;
-                $b->expiration = $date_exp;
-                $b->time = $time;
-                $b->status = "on";
-                $b->method = "$gateway - $channel";
-                $b->routers = $router_name;
-                $b->type = "PPPOE";
-                if ($admin) {
-                    $b->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $b->admin_id = '0';
-                }
-                $b->save();
-
-                // insert table transactions
-                $t = ORM::for_table('tbl_transactions')->create();
-                $t->invoice = $inv = "INV-" . Package::_raid();
-                $t->username = $c['username'];
-                $t->plan_name = $p['name_plan'];
-                if ($p['validity_unit'] == 'Period') {
-                    // Postpaid price from field
-                    $add_inv = User::getAttribute("Invoice", $id_customer);
-                    if (empty($add_inv) or $add_inv == 0) {
-                        $t->price = $p['price'] + $add_cost;
-                    } else {
-                        $t->price = $add_inv + $add_cost;
-                    }
-                } else {
-                    $t->price = $p['price'] + $add_cost;
-                }
-                $t->recharged_on = $date_only;
-                $t->recharged_time = $time_only;
-                $t->expiration = $date_exp;
-                $t->time = $time;
-                $t->method = "$gateway - $channel";
-                $t->routers = $router_name;
-                $t->note = $note;
-                $t->type = "PPPOE";
-                if ($admin) {
-                    $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $t->admin_id = '0';
-                }
-                $t->save();
-
-                if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
-                    // insert price to fields for invoice next month
-                    $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
-                    if (!$fl) {
-                        $fl = ORM::for_table('tbl_customers_fields')->create();
-                        $fl->customer_id = $c['id'];
-                        $fl->field_name = 'Invoice';
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    } else {
-                        $fl->customer_id = $c['id'];
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    }
-                }
-
-                Message::sendTelegram("#u$c[username] $c[fullname] #recharge #PPPOE \n" . $p['name_plan'] .
-                    "\nRouter: " . $router_name .
-                    "\nGateway: " . $gateway .
-                    "\nChannel: " . $channel .
-                    "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
-                    "\nNote:\n" . $note);
+            // plan not exists
+            $dvc = $DEVICE_PATH . DIRECTORY_SEPARATOR . $p['device'] . '.php';
+            if (file_exists($dvc)) {
+                include $dvc;
+                new $p['device']->connect_customer($c, $p);
             } else {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p, "$date_exp $time");
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removePpoeUser($client, $c['username']);
-                    Mikrotik::removePpoeActive($client, $c['username']);
-                    Mikrotik::addPpoeUser($client, $p, $c);
-                }
-
-                $d = ORM::for_table('tbl_user_recharges')->create();
-                $d->customer_id = $id_customer;
-                $d->username = $c['username'];
-                $d->plan_id = $plan_id;
-                $d->namebp = $p['name_plan'];
-                $d->recharged_on = $date_only;
-                $d->recharged_time = $time_only;
-                $d->expiration = $date_exp;
-                $d->time = $time;
-                $d->status = "on";
-                $d->method = "$gateway - $channel";
-                $d->routers = $router_name;
-                $d->type = "PPPOE";
-                if ($admin) {
-                    $d->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $d->admin_id = '0';
-                }
-                $d->save();
-
-                // insert table transactions
-                $t = ORM::for_table('tbl_transactions')->create();
-                $t->invoice = $inv = "INV-" . Package::_raid();
-                $t->username = $c['username'];
-                $t->plan_name = $p['name_plan'];
-                if ($p['validity_unit'] == 'Period') {
-                    // Postpaid price always zero for first time
-                    $note = '';
-                    $bills = [];
-                    $t->price = 0;
-                } else {
-                    $t->price = $p['price'] + $add_cost;
-                }
-                $t->recharged_on = $date_only;
-                $t->recharged_time = $time_only;
-                $t->expiration = $date_exp;
-                $t->time = $time;
-                $t->method = "$gateway - $channel";
-                $t->note = $note;
-                $t->routers = $router_name;
-                if ($admin) {
-                    $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
-                } else {
-                    $t->admin_id = '0';
-                }
-                $t->type = "PPPOE";
-                $t->save();
-
-                if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
-                    // insert price to fields for invoice next month
-                    $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
-                    if (!$fl) {
-                        $fl = ORM::for_table('tbl_customers_fields')->create();
-                        $fl->customer_id = $c['id'];
-                        $fl->field_name = 'Invoice';
-                        // Calculating Price
-                        $sd = new DateTime("$date_only");
-                        $ed = new DateTime("$date_exp");
-                        $td = $ed->diff($sd);
-                        $fd = $td->format("%a");
-                        $gi = ($p['price'] / (30 * $p['validity'])) * $fd;
-                        if ($gi > $p['price']) {
-                            $fl->field_value = $p['price'];
-                        } else {
-                            $fl->field_value = $gi;
-                        }
-                        $fl->save();
-                    } else {
-                        $fl->customer_id = $c['id'];
-                        $fl->field_value = $p['price'];
-                        $fl->save();
-                    }
-                }
-
-                Message::sendTelegram("#u$c[username] $c[fullname] #buy #PPPOE \n" . $p['name_plan'] .
-                    "\nRouter: " . $router_name .
-                    "\nGateway: " . $gateway .
-                    "\nChannel: " . $channel .
-                    "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
-                    "\nNote:\n" . $note);
+                new Exception(Lang::T("Devices Not Found"));
             }
+
+            $d = ORM::for_table('tbl_user_recharges')->create();
+            $d->customer_id = $id_customer;
+            $d->username = $c['username'];
+            $d->plan_id = $plan_id;
+            $d->namebp = $p['name_plan'];
+            $d->recharged_on = $date_only;
+            $d->recharged_time = $time_only;
+            $d->expiration = $date_exp;
+            $d->time = $time;
+            $d->status = "on";
+            $d->method = "$gateway - $channel";
+            $d->routers = $router_name;
+            $d->type = $p['type'];
+            if ($admin) {
+                $d->admin_id = ($admin['id']) ? $admin['id'] : '0';
+            } else {
+                $d->admin_id = '0';
+            }
+            $d->save();
+
+            // insert table transactions
+            $t = ORM::for_table('tbl_transactions')->create();
+            $t->invoice = $inv = "INV-" . Package::_raid();
+            $t->username = $c['username'];
+            $t->plan_name = $p['name_plan'];
+            if ($p['validity_unit'] == 'Period') {
+                // Postpaid price always zero for first time
+                $note = '';
+                $bills = [];
+                $t->price = 0;
+            } else {
+                $t->price = $p['price'] + $add_cost;
+            }
+            $t->recharged_on = $date_only;
+            $t->recharged_time = $time_only;
+            $t->expiration = $date_exp;
+            $t->time = $time;
+            $t->method = "$gateway - $channel";
+            $t->note = $note;
+            $t->routers = $router_name;
+            if ($admin) {
+                $t->admin_id = ($admin['id']) ? $admin['id'] : '0';
+            } else {
+                $t->admin_id = '0';
+            }
+            $t->type = $p['type'];
+            $t->save();
+
+            if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
+                // insert price to fields for invoice next month
+                $fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
+                if (!$fl) {
+                    $fl = ORM::for_table('tbl_customers_fields')->create();
+                    $fl->customer_id = $c['id'];
+                    $fl->field_name = 'Invoice';
+                    // Calculating Price
+                    $sd = new DateTime("$date_only");
+                    $ed = new DateTime("$date_exp");
+                    $td = $ed->diff($sd);
+                    $fd = $td->format("%a");
+                    $gi = ($p['price'] / (30 * $p['validity'])) * $fd;
+                    if ($gi > $p['price']) {
+                        $fl->field_value = $p['price'];
+                    } else {
+                        $fl->field_value = $gi;
+                    }
+                    $fl->save();
+                } else {
+                    $fl->customer_id = $c['id'];
+                    $fl->field_value = $p['price'];
+                    $fl->save();
+                }
+            }
+
+            Message::sendTelegram("#u$c[username] $c[fullname] #buy #$p[type] \n" . $p['name_plan'] .
+                "\nRouter: " . $router_name .
+                "\nGateway: " . $gateway .
+                "\nChannel: " . $channel .
+                "\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
+                "\nNote:\n" . $note);
         }
+
         if (is_array($bills) && count($bills) > 0) {
             User::billsPaid($bills, $id_customer);
         }
@@ -611,81 +407,91 @@ class Package
 
     public static function changeTo($username, $plan_id, $from_id)
     {
+        global $DEVICE_PATH;
         $c = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
         $p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
         $b = ORM::for_table('tbl_user_recharges')->find_one($from_id);
-        if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
-            $mikrotik = Mikrotik::info($p['routers']);
+
+        $dvc = $DEVICE_PATH . DIRECTORY_SEPARATOR . $p['device'] . '.php';
+        if (file_exists($dvc)) {
+            include $dvc;
+            new $p['device']->change_customer($b, $c, $p);
         } else {
-            $mikrotik = Mikrotik::info($b['routers']);
-        }
-        // delete first
-        if ($p['type'] == 'Hotspot') {
-            if ($b) {
-                if (!$p['is_radius']) {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removeHotspotUser($client, $c['username']);
-                    Mikrotik::removeHotspotActiveUser($client, $c['username']);
-                }
-            } else {
-                if (!$p['is_radius']) {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removeHotspotUser($client, $c['username']);
-                    Mikrotik::removeHotspotActiveUser($client, $c['username']);
-                }
-            }
-        } else {
-            if ($b) {
-                if (!$p['is_radius']) {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removePpoeUser($client, $c['username']);
-                    Mikrotik::removePpoeActive($client, $c['username']);
-                }
-            } else {
-                if (!$p['is_radius']) {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::removePpoeUser($client, $c['username']);
-                    Mikrotik::removePpoeActive($client, $c['username']);
-                }
-            }
-        }
-        // call the next mikrotik
-        if ($p['routers'] != $b['routers'] && $p['routers'] != 'radius') {
-            $mikrotik = Mikrotik::info($p['routers']);
-        }
-        if ($p['type'] == 'Hotspot') {
-            if ($b) {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::addHotspotUser($client, $p, $c);
-                }
-            } else {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::addHotspotUser($client, $p, $c);
-                }
-            }
-        } else {
-            if ($b) {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p);
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::addPpoeUser($client, $p, $c);
-                }
-            } else {
-                if ($p['is_radius']) {
-                    Radius::customerAddPlan($c, $p);
-                } else {
-                    $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
-                    Mikrotik::addPpoeUser($client, $p, $c);
-                }
-            }
+            new Exception(Lang::T("Devices Not Found"));
         }
+
+        // if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
+        //     $mikrotik = Mikrotik::info($p['routers']);
+        // } else {
+        //     $mikrotik = Mikrotik::info($b['routers']);
+        // }
+        // // delete first
+        // if ($p['type'] == 'Hotspot') {
+        //     if ($b) {
+        //         if (!$p['is_radius']) {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::removeHotspotUser($client, $c['username']);
+        //             Mikrotik::removeHotspotActiveUser($client, $c['username']);
+        //         }
+        //     } else {
+        //         if (!$p['is_radius']) {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::removeHotspotUser($client, $c['username']);
+        //             Mikrotik::removeHotspotActiveUser($client, $c['username']);
+        //         }
+        //     }
+        // } else {
+        //     if ($b) {
+        //         if (!$p['is_radius']) {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::removePpoeUser($client, $c['username']);
+        //             Mikrotik::removePpoeActive($client, $c['username']);
+        //         }
+        //     } else {
+        //         if (!$p['is_radius']) {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::removePpoeUser($client, $c['username']);
+        //             Mikrotik::removePpoeActive($client, $c['username']);
+        //         }
+        //     }
+        // }
+        // // call the next mikrotik
+        // if ($p['routers'] != $b['routers'] && $p['routers'] != 'radius') {
+        //     $mikrotik = Mikrotik::info($p['routers']);
+        // }
+        // if ($p['type'] == 'Hotspot') {
+        //     if ($b) {
+        //         if ($p['is_radius']) {
+        //             Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
+        //         } else {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::addHotspotUser($client, $p, $c);
+        //         }
+        //     } else {
+        //         if ($p['is_radius']) {
+        //             Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
+        //         } else {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::addHotspotUser($client, $p, $c);
+        //         }
+        //     }
+        // } else {
+        //     if ($b) {
+        //         if ($p['is_radius']) {
+        //             Radius::customerAddPlan($c, $p);
+        //         } else {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::addPpoeUser($client, $p, $c);
+        //         }
+        //     } else {
+        //         if ($p['is_radius']) {
+        //             Radius::customerAddPlan($c, $p);
+        //         } else {
+        //             $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        //             Mikrotik::addPpoeUser($client, $p, $c);
+        //         }
+        //     }
+        // }
     }
 
 
diff --git a/system/cron.php b/system/cron.php
index 5038aa7e..f08361ea 100644
--- a/system/cron.php
+++ b/system/cron.php
@@ -24,124 +24,74 @@ echo "Found " . count($d) . " user(s)\n";
 run_hook('cronjob'); #HOOK
 
 foreach ($d as $ds) {
-    if ($ds['type'] == 'Hotspot') { # HOTSPOT
-        $date_now = strtotime(date("Y-m-d H:i:s"));
-        $expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
-        echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
-        if ($date_now >= $expiration) {
-            echo " : EXPIRED \r\n";
-            $u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
-            $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
-            $m = Mikrotik::info($ds['routers']);
-            $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
-            if ($p['is_radius']) {
-                if (empty($p['pool_expired'])) {
-                    print_r(Radius::customerDeactivate($c['username']));
+    $date_now = strtotime(date("Y-m-d H:i:s"));
+    $expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
+    echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
+    if ($date_now >= $expiration) {
+        echo " : EXPIRED \r\n";
+        $u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
+        $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
+        $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
+        $dvc = $DEVICE_PATH . DIRECTORY_SEPARATOR . $p['device'].'.php';
+        if(file_exists($dvc)){
+            include $dvc;
+            new $p['device']->disconnect_customer($ds['routers'], $c, $p);
+        }else{
+            echo "Cron error Devices $p[device] not found, cannot disconnect $c[username]";
+            Message::sendTelegram("Cron error Devices $p[device] not found, cannot disconnect $c[username]");
+        }
+        // if ($p['is_radius']) {
+        //     if (empty($p['pool_expired'])) {
+        //         print_r(Radius::customerDeactivate($c['username']));
+        //     } else {
+        //         Radius::upsertCustomerAttr($c['username'], 'Framed-Pool', $p['pool_expired'], ':=');
+        //         print_r(Radius::disconnectCustomer($c['username']));
+        //     }
+        // } else {
+        //     $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
+        //     if (!empty($p['pool_expired'])) {
+        //         Mikrotik::setHotspotUserPackage($client, $c['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
+        //         // }if (!empty($p['list_expired'])) {
+        //         //     $ip = Mikrotik::getIpHotspotUser($client, $ds['username']);
+        //         //     Mikrotik::addIpToAddressList($client, $ip, $p['list_expired'], $c['username']);
+        //     } else {
+        //         Mikrotik::removeHotspotUser($client, $c['username']);
+        //     }
+        //     Mikrotik::removeHotspotActiveUser($client, $c['username']);
+        // }
+        echo Message::sendPackageNotification($c, $u['namebp'], $p['price'], $textExpired, $config['user_notification_expired']) . "\n";
+        //update database user dengan status off
+        $u->status = 'off';
+        $u->save();
+
+        // autorenewal from deposit
+        if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
+            list($bills, $add_cost) = User::getBills($ds['customer_id']);
+            if ($add_cost > 0) {
+                if (!empty($add_cost)) {
+                    $p['price'] += $add_cost;
+                }
+            }
+            if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
+                if (Package::rechargeUser($ds['customer_id'], $ds['routers'], $p['id'], 'Customer', 'Balance')) {
+                    // if success, then get the balance
+                    Balance::min($ds['customer_id'], $p['price']);
+                    echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
+                    echo "auto renewall Success\n";
                 } else {
-                    Radius::upsertCustomerAttr($c['username'], 'Framed-Pool', $p['pool_expired'], ':=');
-                    print_r(Radius::disconnectCustomer($c['username']));
+                    echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
+                    echo "auto renewall Failed\n";
+                    Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #Hotspot \n" . $p['name_plan'] .
+                        "\nRouter: " . $p['routers'] .
+                        "\nPrice: " . $p['price']);
                 }
             } else {
-                $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
-                if (!empty($p['pool_expired'])) {
-                    Mikrotik::setHotspotUserPackage($client, $c['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
-                    // }if (!empty($p['list_expired'])) {
-                    //     $ip = Mikrotik::getIpHotspotUser($client, $ds['username']);
-                    //     Mikrotik::addIpToAddressList($client, $ip, $p['list_expired'], $c['username']);
-                } else {
-                    Mikrotik::removeHotspotUser($client, $c['username']);
-                }
-                Mikrotik::removeHotspotActiveUser($client, $c['username']);
+                echo "no renewall | plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
             }
-            echo Message::sendPackageNotification($c, $u['namebp'], $p['price'], $textExpired, $config['user_notification_expired']) . "\n";
-            //update database user dengan status off
-            $u->status = 'off';
-            $u->save();
-
-            // autorenewal from deposit
-            if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
-                list($bills, $add_cost) = User::getBills($ds['customer_id']);
-                if ($add_cost > 0) {
-                    if (!empty($add_cost)) {
-                        $p['price'] += $add_cost;
-                    }
-                }
-                if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
-                    if (Package::rechargeUser($ds['customer_id'], $ds['routers'], $p['id'], 'Customer', 'Balance')) {
-                        // if success, then get the balance
-                        Balance::min($ds['customer_id'], $p['price']);
-                        echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
-                        echo "auto renewall Success\n";
-                    } else {
-                        echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
-                        echo "auto renewall Failed\n";
-                        Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #Hotspot \n" . $p['name_plan'] .
-                            "\nRouter: " . $p['routers'] .
-                            "\nPrice: " . $p['price']);
-                    }
-                } else {
-                    echo "no renewall | plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
-                }
-            } else {
-                echo "no renewall | balance $config[enable_balance] auto_renewal $c[auto_renewal]\n";
-            }
-        } else
-            echo " : ACTIVE \r\n";
-    } else { # PPPOE
-        $date_now = strtotime(date("Y-m-d H:i:s"));
-        $expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
-        echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
-        if ($date_now >= $expiration) {
-            echo " : EXPIRED \r\n";
-            $u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
-            $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
-            $m = ORM::for_table('tbl_routers')->where('name', $ds['routers'])->find_one();
-            $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
-            if ($p['is_radius']) {
-                if (empty($p['pool_expired'])) {
-                    print_r(Radius::customerDeactivate($c['username']));
-                } else {
-                    Radius::upsertCustomerAttr($c['username'], 'Framed-Pool', $p['pool_expired'], ':=');
-                    print_r(Radius::disconnectCustomer($c['username']));
-                }
-            } else {
-                $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
-                if (!empty($p['pool_expired'])) {
-                    Mikrotik::setPpoeUserPlan($client, $c['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
-                } else {
-                    Mikrotik::removePpoeUser($client, $c['username']);
-                }
-                Mikrotik::removePpoeActive($client, $c['username']);
-            }
-            echo Message::sendPackageNotification($c, $u['namebp'], $p['price'], $textExpired, $config['user_notification_expired']) . "\n";
-
-            $u->status = 'off';
-            $u->save();
-
-            // autorenewal from deposit
-            if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
-                list($bills, $add_cost) = User::getBills($ds['customer_id']);
-                if ($add_cost > 0) {
-                    if (!empty($add_cost)) {
-                        $p['price'] += $add_cost;
-                    }
-                }
-                if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
-                    if (Package::rechargeUser($ds['customer_id'], $ds['routers'], $p['id'], 'Customer', 'Balance')) {
-                        // if success, then get the balance
-                        Balance::min($ds['customer_id'], $p['price']);
-                        echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
-                        echo "auto renewall Success\n";
-                    } else {
-                        echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
-                        echo "auto renewall Failed\n";
-                        Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #PPPOE \n" . $p['name_plan'] .
-                            "\nRouter: " . $p['routers'] .
-                            "\nPrice: " . $p['price']);
-                    }
-                }
-            }
-        } else
-            echo " : ACTIVE \r\n";
+        } else {
+            echo "no renewall | balance $config[enable_balance] auto_renewal $c[auto_renewal]\n";
+        }
+    } else{
+        echo " : ACTIVE \r\n";
     }
 }
diff --git a/system/devices/MikrotikHotspot.php b/system/devices/MikrotikHotspot.php
index 952170a1..33eb3253 100644
--- a/system/devices/MikrotikHotspot.php
+++ b/system/devices/MikrotikHotspot.php
@@ -13,17 +13,144 @@ use PEAR2\Net\RouterOS;
 class MikrotikHotspot
 {
 
-    function connect_customer($router, $customer, $plan)
+    function connect_customer($customer, $plan)
     {
-        $mikrotik = $this->info($router);
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
         $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
         Mikrotik::removeHotspotUser($client, $customer['username']);
         Mikrotik::removeHotspotActiveUser($client, $customer['username']);
         Mikrotik::addHotspotUser($client, $plan, $customer);
     }
 
-    function disconnect_customer($routers, $customer)
+    function disconnect_customer($customer, $plan)
     {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if (!empty($p['pool_expired'])) {
+            Mikrotik::setHotspotUserPackage($client, $customer['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
+        } else {
+            Mikrotik::removeHotspotUser($client, $customer['username']);
+        }
+        Mikrotik::removeHotspotActiveUser($client, $customer['username']);
+    }
+
+    function change_customer($tur, $customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        Mikrotik::removeHotspotUser($client, $customer['username']);
+        Mikrotik::removeHotspotActiveUser($client, $customer['username']);
+        Mikrotik::addHotspotUser($client, $plan, $customer);
+    }
+
+    function add_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if ($plan['rate_down_unit'] == 'Kbps') {
+            $unitdown = 'K';
+        } else {
+            $unitdown = 'M';
+        }
+        if ($plan['rate_up_unit'] == 'Kbps') {
+            $unitup = 'K';
+        } else {
+            $unitup = 'M';
+        }
+        $rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown;
+        $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
+        $client->sendSync(
+            $addRequest
+                ->setArgument('name', $plan['name_plan'])
+                ->setArgument('shared-users', $plan['shared_users'])
+                ->setArgument('rate-limit', $rate)
+        );
+    }
+
+    function update_plan($old_plan, $new_plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($new_plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if ($new_plan['rate_down_unit'] == 'Kbps') {
+            $unitdown = 'K';
+        } else {
+            $unitdown = 'M';
+        }
+        if ($new_plan['rate_up_unit'] == 'Kbps') {
+            $unitup = 'K';
+        } else {
+            $unitup = 'M';
+        }
+        $rate = $new_plan['rate_up'] . $unitup . "/" . $new_plan['rate_down'] . $unitdown;
+        $printRequest = new RouterOS\Request(
+            '/ip hotspot user profile print .proplist=.id',
+            RouterOS\Query::where('name', $old_plan['name_plan'])
+        );
+        $profileID = $client->sendSync($printRequest)->getProperty('.id');
+        if (empty($profileID)) {
+            Mikrotik::addHotspotPlan($client, $new_plan['name_plan'], $new_plan['shared_users'], $rate);
+        } else {
+            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
+            $client->sendSync(
+                $setRequest
+                    ->setArgument('numbers', $profileID)
+                    ->setArgument('name', $new_plan['name_plan'])
+                    ->setArgument('shared-users', $new_plan['shared_users'])
+                    ->setArgument('rate-limit', $rate)
+            );
+        }
+    }
+
+    function remove_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        $printRequest = new RouterOS\Request(
+            '/ip hotspot user profile print .proplist=.id',
+            RouterOS\Query::where('name', $plan['name_plan'])
+        );
+        $profileID = $client->sendSync($printRequest)->getProperty('.id');
+        $removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
+        $client->sendSync(
+            $removeRequest
+                ->setArgument('numbers', $profileID)
+        );
+    }
+
+    function add_pool($pool){
+        // Hotspot no need pool
+    }
+
+    function update_pool($old_pool, $new_pool){
+        // Hotspot no need pool
+    }
+
+    function remove_pool($pool){
+        // Hotspot no need pool
     }
 
     function info($name)
@@ -88,96 +215,6 @@ class MikrotikHotspot
         );
     }
 
-    function addHotspotPlan($client, $name, $sharedusers, $rate)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
-        $client->sendSync(
-            $addRequest
-                ->setArgument('name', $name)
-                ->setArgument('shared-users', $sharedusers)
-                ->setArgument('rate-limit', $rate)
-        );
-    }
-
-    function setHotspotPlan($client, $name, $sharedusers, $rate)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-        if (empty($profileID)) {
-            Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate);
-        } else {
-            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
-            $client->sendSync(
-                $setRequest
-                    ->setArgument('numbers', $profileID)
-                    ->setArgument('shared-users', $sharedusers)
-                    ->setArgument('rate-limit', $rate)
-            );
-        }
-    }
-
-    function setHotspotExpiredPlan($client, $name, $pool)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-        if (empty($profileID)) {
-            $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
-            $client->sendSync(
-                $addRequest
-                    ->setArgument('name', $name)
-                    ->setArgument('shared-users', 3)
-                    ->setArgument('address-pool', $pool)
-                    ->setArgument('rate-limit', '512K/512K')
-            );
-        } else {
-            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
-            $client->sendSync(
-                $setRequest
-                    ->setArgument('numbers', $profileID)
-                    ->setArgument('shared-users', 3)
-                    ->setArgument('address-pool', $pool)
-                    ->setArgument('rate-limit', '512K/512K')
-            );
-        }
-    }
-
-    function removeHotspotPlan($client, $name)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-
-        $removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $profileID)
-        );
-    }
-
     function removeHotspotUser($client, $username)
     {
         global $_app_stage;
@@ -339,37 +376,4 @@ class MikrotikHotspot
         );
         return $client->sendSync($printRequest)->getProperty('address');
     }
-
-    function addIpToAddressList($client, $ip, $listName, $comment = '')
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $addRequest = new RouterOS\Request('/ip/firewall/address-list/add');
-        $client->sendSync(
-            $addRequest
-                ->setArgument('address', $ip)
-                ->setArgument('comment', $comment)
-                ->setArgument('list', $listName)
-        );
-    }
-
-    function removeIpFromAddressList($client, $ip)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip firewall address-list print .proplist=.id',
-            RouterOS\Query::where('address', $ip)
-        );
-        $id = $client->sendSync($printRequest)->getProperty('.id');
-        $removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $id)
-        );
-    }
 }
diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php
index 7c000837..39303980 100644
--- a/system/devices/MikrotikPppoe.php
+++ b/system/devices/MikrotikPppoe.php
@@ -10,7 +10,8 @@
 
 use PEAR2\Net\RouterOS;
 
-class MikrotikHotspot {
+class MikrotikHotspot
+{
 
     /**
      * Establishes a connection between a MikroTik router and a customer.
@@ -24,8 +25,17 @@ class MikrotikHotspot {
      *                        such as their username or account details.
      * @return void
      */
-    function connect_customer($routers, $customer){
-
+    function connect_customer($customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        Mikrotik::removePpoeUser($client, $customer['username']);
+        Mikrotik::removePpoeActive($client, $customer['username']);
+        Mikrotik::addPpoeUser($client, $plan, $customer);
     }
 
     /**
@@ -40,8 +50,179 @@ class MikrotikHotspot {
      *                        such as their username or account details.
      * @return void
      */
-    function disconnect_customer($routers, $customer){
+    function disconnect_customer($customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if (!empty($p['pool_expired'])) {
+            Mikrotik::setPpoeUserPlan($client, $customer['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
+        } else {
+            Mikrotik::removePpoeUser($client, $customer['username']);
+        }
+        Mikrotik::removePpoeActive($client, $customer['username']);
+    }
 
+    function change_customer($tur, $customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        Mikrotik::removePpoeUser($client, $customer['username']);
+        Mikrotik::removePpoeActive($client, $customer['username']);
+        Mikrotik::addPpoeUser($client, $plan, $customer);
+    }
+
+
+    function add_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if ($plan['rate_down_unit'] == 'Kbps') {
+            $unitdown = 'K';
+        } else {
+            $unitdown = 'M';
+        }
+        if ($plan['rate_up_unit'] == 'Kbps') {
+            $unitup = 'K';
+        } else {
+            $unitup = 'M';
+        }
+        $rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown;
+        $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
+        $client->sendSync(
+            $addRequest
+                ->setArgument('name', $plan['name_plan'])
+                ->setArgument('shared-users', $plan['shared_users'])
+                ->setArgument('rate-limit', $rate)
+        );
+    }
+
+    function update_plan($old_name, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        if ($plan['rate_down_unit'] == 'Kbps') {
+            $unitdown = 'K';
+        } else {
+            $unitdown = 'M';
+        }
+        if ($plan['rate_up_unit'] == 'Kbps') {
+            $unitup = 'K';
+        } else {
+            $unitup = 'M';
+        }
+        $rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown;
+        $printRequest = new RouterOS\Request(
+            '/ip hotspot user profile print .proplist=.id',
+            RouterOS\Query::where('name', $old_name)
+        );
+        $profileID = $client->sendSync($printRequest)->getProperty('.id');
+        if (empty($profileID)) {
+            Mikrotik::addHotspotPlan($client, $plan['name_plan'], $plan['shared_users'], $rate);
+        } else {
+            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
+            $client->sendSync(
+                $setRequest
+                    ->setArgument('numbers', $profileID)
+                    ->setArgument('name', $plan['name_plan'])
+                    ->setArgument('shared-users', $plan['shared_users'])
+                    ->setArgument('rate-limit', $rate)
+            );
+        }
+    }
+
+    function remove_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+        $mikrotik = $this->info($plan['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        $printRequest = new RouterOS\Request(
+            '/ip hotspot user profile print .proplist=.id',
+            RouterOS\Query::where('name', $plan['name_plan'])
+        );
+        $profileID = $client->sendSync($printRequest)->getProperty('.id');
+        $removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
+        $client->sendSync(
+            $removeRequest
+                ->setArgument('numbers', $profileID)
+        );
+    }
+
+    function add_pool($pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+        $mikrotik = $this->info($pool['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        $addRequest = new RouterOS\Request('/ip/pool/add');
+        $client->sendSync(
+            $addRequest
+                ->setArgument('name', $pool['pool_name'])
+                ->setArgument('ranges', $pool['range_ip'])
+        );
+    }
+
+    function update_pool($old_pool, $new_pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+        $mikrotik = $this->info($new_pool['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        $printRequest = new RouterOS\Request(
+            '/ip pool print .proplist=.id',
+            RouterOS\Query::where('name', $old_pool['pool_name'])
+        );
+        $poolID = $client->sendSync($printRequest)->getProperty('.id');
+        if (empty($poolID)) {
+            $this->add_pool($new_pool);
+        } else {
+            $setRequest = new RouterOS\Request('/ip/pool/set');
+            $client->sendSync(
+                $setRequest
+                    ->setArgument('numbers', $poolID)
+                    ->setArgument('name', $new_pool['pool_name'])
+                    ->setArgument('ranges', $new_pool['range_ip'])
+            );
+        }
+    }
+
+    function remove_pool($pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+        $mikrotik = $this->info($pool['routers']);
+        $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+        $printRequest = new RouterOS\Request(
+            '/ip pool print .proplist=.id',
+            RouterOS\Query::where('name', $pool['pool_name'])
+        );
+        $poolID = $client->sendSync($printRequest)->getProperty('.id');
+        $removeRequest = new RouterOS\Request('/ip/pool/remove');
+        $client->sendSync(
+            $removeRequest
+                ->setArgument('numbers', $poolID)
+        );
     }
 
     function info($name)
@@ -87,251 +268,6 @@ class MikrotikHotspot {
                 ->setArgument('mac-address', $mac)
         );
     }
-
-    function logMeOut($client, $user)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot active print',
-            RouterOS\Query::where('user', $user)
-        );
-        $id = $client->sendSync($printRequest)->getProperty('.id');
-        $removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $id)
-        );
-    }
-
-    function addHotspotPlan($client, $name, $sharedusers, $rate)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
-        $client->sendSync(
-            $addRequest
-                ->setArgument('name', $name)
-                ->setArgument('shared-users', $sharedusers)
-                ->setArgument('rate-limit', $rate)
-        );
-    }
-
-    function setHotspotPlan($client, $name, $sharedusers, $rate)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-        if (empty($profileID)) {
-            Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate);
-        } else {
-            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
-            $client->sendSync(
-                $setRequest
-                    ->setArgument('numbers', $profileID)
-                    ->setArgument('shared-users', $sharedusers)
-                    ->setArgument('rate-limit', $rate)
-            );
-        }
-    }
-
-    function setHotspotExpiredPlan($client, $name, $pool)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-        if (empty($profileID)) {
-            $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
-            $client->sendSync(
-                $addRequest
-                    ->setArgument('name', $name)
-                    ->setArgument('shared-users', 3)
-                    ->setArgument('address-pool', $pool)
-                    ->setArgument('rate-limit', '512K/512K')
-            );
-        } else {
-            $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
-            $client->sendSync(
-                $setRequest
-                    ->setArgument('numbers', $profileID)
-                    ->setArgument('shared-users', 3)
-                    ->setArgument('address-pool', $pool)
-                    ->setArgument('rate-limit', '512K/512K')
-            );
-        }
-    }
-
-    function removeHotspotPlan($client, $name)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user profile print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $profileID = $client->sendSync($printRequest)->getProperty('.id');
-
-        $removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $profileID)
-        );
-    }
-
-    function removeHotspotUser($client, $username)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip hotspot user print .proplist=.id',
-            RouterOS\Query::where('name', $username)
-        );
-        $userID = $client->sendSync($printRequest)->getProperty('.id');
-        $removeRequest = new RouterOS\Request('/ip/hotspot/user/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $userID)
-        );
-    }
-
-    function addHotspotUser($client, $plan, $customer)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $addRequest = new RouterOS\Request('/ip/hotspot/user/add');
-        if ($plan['typebp'] == "Limited") {
-            if ($plan['limit_type'] == "Time_Limit") {
-                if ($plan['time_unit'] == 'Hrs')
-                    $timelimit = $plan['time_limit'] . ":00:00";
-                else
-                    $timelimit = "00:" . $plan['time_limit'] . ":00";
-                $client->sendSync(
-                    $addRequest
-                        ->setArgument('name', $customer['username'])
-                        ->setArgument('profile', $plan['name_plan'])
-                        ->setArgument('password', $customer['password'])
-                        ->setArgument('comment', $customer['fullname'])
-                        ->setArgument('email', $customer['email'])
-                        ->setArgument('limit-uptime', $timelimit)
-                );
-            } else if ($plan['limit_type'] == "Data_Limit") {
-                if ($plan['data_unit'] == 'GB')
-                    $datalimit = $plan['data_limit'] . "000000000";
-                else
-                    $datalimit = $plan['data_limit'] . "000000";
-                $client->sendSync(
-                    $addRequest
-                        ->setArgument('name', $customer['username'])
-                        ->setArgument('profile', $plan['name_plan'])
-                        ->setArgument('password', $customer['password'])
-                        ->setArgument('comment', $customer['fullname'])
-                        ->setArgument('email', $customer['email'])
-                        ->setArgument('limit-bytes-total', $datalimit)
-                );
-            } else if ($plan['limit_type'] == "Both_Limit") {
-                if ($plan['time_unit'] == 'Hrs')
-                    $timelimit = $plan['time_limit'] . ":00:00";
-                else
-                    $timelimit = "00:" . $plan['time_limit'] . ":00";
-                if ($plan['data_unit'] == 'GB')
-                    $datalimit = $plan['data_limit'] . "000000000";
-                else
-                    $datalimit = $plan['data_limit'] . "000000";
-                $client->sendSync(
-                    $addRequest
-                        ->setArgument('name', $customer['username'])
-                        ->setArgument('profile', $plan['name_plan'])
-                        ->setArgument('password', $customer['password'])
-                        ->setArgument('comment', $customer['fullname'])
-                        ->setArgument('email', $customer['email'])
-                        ->setArgument('limit-uptime', $timelimit)
-                        ->setArgument('limit-bytes-total', $datalimit)
-                );
-            }
-        } else {
-            $client->sendSync(
-                $addRequest
-                    ->setArgument('name', $customer['username'])
-                    ->setArgument('profile', $plan['name_plan'])
-                    ->setArgument('comment', $customer['fullname'])
-                    ->setArgument('email', $customer['email'])
-                    ->setArgument('password', $customer['password'])
-            );
-        }
-    }
-
-    function setHotspotUser($client, $user, $pass)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request('/ip/hotspot/user/print');
-        $printRequest->setArgument('.proplist', '.id');
-        $printRequest->setQuery(RouterOS\Query::where('name', $user));
-        $id = $client->sendSync($printRequest)->getProperty('.id');
-
-        $setRequest = new RouterOS\Request('/ip/hotspot/user/set');
-        $setRequest->setArgument('numbers', $id);
-        $setRequest->setArgument('password', $pass);
-        $client->sendSync($setRequest);
-    }
-
-    function setHotspotUserPackage($client, $user, $plan)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request('/ip/hotspot/user/print');
-        $printRequest->setArgument('.proplist', '.id');
-        $printRequest->setQuery(RouterOS\Query::where('name', $user));
-        $id = $client->sendSync($printRequest)->getProperty('.id');
-
-        $setRequest = new RouterOS\Request('/ip/hotspot/user/set');
-        $setRequest->setArgument('numbers', $id);
-        $setRequest->setArgument('profile', $plan);
-        $client->sendSync($setRequest);
-    }
-
-    function removeHotspotActiveUser($client, $username)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $onlineRequest = new RouterOS\Request('/ip/hotspot/active/print');
-        $onlineRequest->setArgument('.proplist', '.id');
-        $onlineRequest->setQuery(RouterOS\Query::where('user', $username));
-        $id = $client->sendSync($onlineRequest)->getProperty('.id');
-
-        $removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
-        $removeRequest->setArgument('numbers', $id);
-        $client->sendSync($removeRequest);
-    }
-
     function removePpoeUser($client, $username)
     {
         global $_app_stage;
@@ -419,64 +355,6 @@ class MikrotikHotspot {
         $client->sendSync($removeRequest);
     }
 
-    function removePool($client, $name)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip pool print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $poolID = $client->sendSync($printRequest)->getProperty('.id');
-
-        $removeRequest = new RouterOS\Request('/ip/pool/remove');
-        $client->sendSync(
-            $removeRequest
-                ->setArgument('numbers', $poolID)
-        );
-    }
-
-    function addPool($client, $name, $ip_address)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $addRequest = new RouterOS\Request('/ip/pool/add');
-        $client->sendSync(
-            $addRequest
-                ->setArgument('name', $name)
-                ->setArgument('ranges', $ip_address)
-        );
-    }
-
-    function setPool($client, $name, $ip_address)
-    {
-        global $_app_stage;
-        if ($_app_stage == 'demo') {
-            return null;
-        }
-        $printRequest = new RouterOS\Request(
-            '/ip pool print .proplist=.id',
-            RouterOS\Query::where('name', $name)
-        );
-        $poolID = $client->sendSync($printRequest)->getProperty('.id');
-
-        if (empty($poolID)) {
-            self::addPool($client, $name, $ip_address);
-        } else {
-            $setRequest = new RouterOS\Request('/ip/pool/set');
-            $client->sendSync(
-                $setRequest
-                    ->setArgument('numbers', $poolID)
-                    ->setArgument('ranges', $ip_address)
-            );
-        }
-    }
-
-
     function addPpoePlan($client, $name, $pool, $rate)
     {
         global $_app_stage;
@@ -550,7 +428,8 @@ class MikrotikHotspot {
         $client->sendSync($smsRequest);
     }
 
-    function getIpHotspotUser($client, $username){
+    function getIpHotspotUser($client, $username)
+    {
         global $_app_stage;
         if ($_app_stage == 'demo') {
             return null;
@@ -594,4 +473,4 @@ class MikrotikHotspot {
                 ->setArgument('numbers', $id)
         );
     }
-}
\ No newline at end of file
+}
diff --git a/system/devices/radius.php b/system/devices/radius.php
index cf4fd3fa..62691406 100644
--- a/system/devices/radius.php
+++ b/system/devices/radius.php
@@ -1,41 +1,37 @@
 <?php
 
-/**
- *  PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
- *  by https://t.me/ibnux
- *
- * This is Core, don't modification except you want to contribute
- * better create new plugin
- **/
+class Radius {
 
-/**
- * Establishes a connection between a MikroTik router and a customer.
- *
- * This function takes two parameters: $routers and $customer.
- *
- * @param array $routers An array containing information about the MikroTik routers.
- *                       This can include IP addresses or connection details.
- * @param mixed $customer An object or array representing a specific customer.
- *                        This can contain relevant information about the customer,
- *                        such as their username or account details.
- * @return void
- */
-function mikrotik_connect_customer($routers, $customer)
-{
-}
+    /**
+     * Establishes a connection between a MikroTik router and a customer.
+     *
+     * This function takes two parameters: $routers and $customer.
+     *
+     * @param array $routers An array containing information about the MikroTik routers.
+     *                       This can include IP addresses or connection details.
+     * @param mixed $customer An object or array representing a specific customer.
+     *                        This can contain relevant information about the customer,
+     *                        such as their username or account details.
+     * @return void
+     */
+    function connect_customer($routers, $customer){
 
-/**
- * Disconnects a customer from a MikroTik router.
- *
- * This function takes two parameters: $routers and $customer.
- *
- * @param array $routers An array containing information about the MikroTik routers.
- *                       This can include IP addresses or connection details.
- * @param mixed $customer An object or array representing a specific customer.
- *                        This can contain relevant information about the customer,
- *                        such as their username or account details.
- * @return void
- */
-function mikrotik_disconnect_customer($routers, $customer)
-{
-}
+    }
+
+    /**
+     * Disconnects a customer from a MikroTik router.
+     *
+     * This function takes two parameters: $routers and $customer.
+     *
+     * @param array $routers An array containing information about the MikroTik routers.
+     *                       This can include IP addresses or connection details.
+     * @param mixed $customer An object or array representing a specific customer.
+     *                        This can contain relevant information about the customer,
+     *                        such as their username or account details.
+     * @return void
+     */
+    function disconnect_customer($routers, $customer){
+
+    }
+
+}
\ No newline at end of file
diff --git a/system/devices/readme.md b/system/devices/readme.md
new file mode 100644
index 00000000..e429558b
--- /dev/null
+++ b/system/devices/readme.md
@@ -0,0 +1,79 @@
+# How To add new Devices
+
+just follow the template
+
+```php
+<?php
+
+class FileName {
+
+    function connect_customer($customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function disconnect_customer($customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function change_customer($tur, $customer, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function add_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function update_plan($old_name, $plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function remove_plan($plan)
+    {
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return;
+        }
+    }
+
+    function add_pool($pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+    }
+
+    function update_pool($old_pool, $new_pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+    }
+
+    function remove_pool($pool){
+        global $_app_stage;
+        if ($_app_stage == 'demo') {
+            return null;
+        }
+    }
+}
+```
\ No newline at end of file