diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 27458ef..38187fa 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -53,4 +53,30 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin', 'filter' => 'au $routes->post('batchjob_delete', 'TrafficController::batchjob_delete'); $routes->get('download/(:alpha)', 'TrafficController::download/$1'); }); + $routes->group('collector', ['namespace' => 'App\Controllers\Admin'], function ($routes) { + $routes->get('/', 'CollectorController::index'); + $routes->get('create', 'CollectorController::create_form'); + $routes->post('create', 'CollectorController::create'); + $routes->get('modify/(:num)', 'CollectorController::modify_form/$1'); + $routes->post('modify/(:num)', 'CollectorController::modify/$1'); + $routes->get('view/(:num)', 'CollectorController::view/$1'); + $routes->get('delete/(:num)', 'CollectorController::delete/$1'); + $routes->get('toggle/(:num)/(:any)', 'CollectorController::toggle/$1/$2'); + $routes->post('batchjob', 'CollectorController::batchjob'); + $routes->post('batchjob_delete', 'CollectorController::batchjob_delete'); + $routes->get('download/(:alpha)', 'CollectorController::download/$1'); + }); + $routes->group('mylog', ['namespace' => 'App\Controllers\Admin'], function ($routes) { + $routes->get('/', 'MylogController::index'); + $routes->get('create', 'MylogController::create_form'); + $routes->post('create', 'MylogController::create'); + $routes->get('modify/(:num)', 'MylogController::modify_form/$1'); + $routes->post('modify/(:num)', 'MylogController::modify/$1'); + $routes->get('view/(:num)', 'MylogController::view/$1'); + $routes->get('delete/(:num)', 'MylogController::delete/$1'); + $routes->get('toggle/(:num)/(:any)', 'MylogController::toggle/$1/$2'); + $routes->post('batchjob', 'MylogController::batchjob'); + $routes->post('batchjob_delete', 'MylogController::batchjob_delete'); + $routes->get('download/(:alpha)', 'MylogController::download/$1'); + }); }); diff --git a/app/Config/Services.php b/app/Config/Services.php index f7bd1ae..3005aa7 100644 --- a/app/Config/Services.php +++ b/app/Config/Services.php @@ -4,6 +4,8 @@ namespace Config; use App\Services\Auth\GoogleService; use App\Services\Auth\LocalService; +use App\Services\CollectorService; +use App\Services\MylogService; use App\Services\TrafficService; use App\Services\UserService; use CodeIgniter\Config\BaseService; @@ -85,4 +87,24 @@ class Services extends BaseService new \App\Models\TrafficModel(), ); } + + public static function collectorservice($getShared = true): CollectorService + { + if ($getShared) { + return static::getSharedInstance(__FUNCTION__); + } + return new CollectorService( + new \App\Models\CollectorModel(), + ); + } + + public static function mylogservice($getShared = true): MylogService + { + if ($getShared) { + return static::getSharedInstance(__FUNCTION__); + } + return new MylogService( + new \App\Models\MylogModel(), + ); + } } diff --git a/app/Controllers/Admin/AdminController.php b/app/Controllers/Admin/AdminController.php index e53ae8c..12069dc 100644 --- a/app/Controllers/Admin/AdminController.php +++ b/app/Controllers/Admin/AdminController.php @@ -53,14 +53,15 @@ abstract class AdminController extends CommonController } return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas()); } - abstract protected function create_process(string $action): string|RedirectResponse; + abstract protected function create_process(string $action): array; final public function create(): string|RedirectResponse { $action = __FUNCTION__; try { //초기화 $this->action_init_process($action); - return $this->create_process($action); + list($entity, $message) = $this->create_process($action); + return $this->action_modal_process($message); } catch (ValidationException $e) { // 검증 실패 시 폼으로 돌아가서 오류 메시지 표시 log_message('error', $e->getMessage()); @@ -84,14 +85,15 @@ abstract class AdminController extends CommonController } return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas()); } - abstract protected function modify_process(string $action, $uid): string|RedirectResponse; + abstract protected function modify_process(string $action, $uid): array; final public function modify($uid): string|RedirectResponse { $action = __FUNCTION__; try { //초기화 $this->action_init_process($action); - return $this->modify_process($action, $uid); + list($entity, $message) = $this->modify_process($action, $uid); + return $this->action_modal_process($message); } catch (ValidationException $e) { // 검증 실패 시 폼으로 돌아가서 오류 메시지 표시 log_message('error', $e->getMessage()); diff --git a/app/Controllers/Admin/CollectorController.php b/app/Controllers/Admin/CollectorController.php new file mode 100644 index 0000000..8b499ed --- /dev/null +++ b/app/Controllers/Admin/CollectorController.php @@ -0,0 +1,58 @@ +service === null) { + $this->service = service('collectorservice'); + } + $this->addActionPaths($this::PATH); + } + //Action작업관련 + protected function create_form_process(string $action): void + { + //Form Default값 설정 + $formDatas = []; + $this->addViewDatas('formDatas', $formDatas); + } + protected function create_process(string $action): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new CollectorDTO($this->request->getPost()); + $entity = $this->service->create($dto); + return array($entity, "{$entity->getTitle()} 수집정보 생성이 완료되었습니다."); + } + protected function modify_form_process(string $action, $uid): void + { + if (!$uid) { + throw new \Exception("수집정보 번호가 정의 되지 않았습니다."); + } + $entity = $this->service->getEntity($uid); + if (!$entity instanceof CollectorEntity) { + throw new \Exception("{$uid}에 해당하는 수집정보를 찾을수 없습니다."); + } + $this->addViewDatas('entity', $entity); + } + protected function modify_process(string $action, $uid): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new CollectorDTO($this->request->getPost()); + $entity = $this->service->modify($uid, $dto); + return array($entity, "{$entity->getTitle()} 수집정보 수정이 완료되었습니다."); + } + protected function view_process($uid): CollectorEntity + { + return parent::view_process($uid); + } +} diff --git a/app/Controllers/Admin/MylogController.php b/app/Controllers/Admin/MylogController.php new file mode 100644 index 0000000..8471321 --- /dev/null +++ b/app/Controllers/Admin/MylogController.php @@ -0,0 +1,59 @@ +service === null) { + $this->service = service('mylogservice'); + } + $this->addActionPaths($this::PATH); + } + + //Action작업관련 + protected function create_form_process(string $action): void + { + //Form Default값 설정 + $formDatas = []; + $this->addViewDatas('formDatas', $formDatas); + } + protected function create_process(string $action): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new MylogDTO($this->request->getPost()); + $entity = $this->service->create($dto); + return array($entity, "{$entity->getTitle()} 로그 생성이 완료되었습니다."); + } + protected function modify_form_process(string $action, $uid): void + { + if (!$uid) { + throw new \Exception("로그 번호가 정의 되지 않았습니다."); + } + $entity = $this->service->getEntity($uid); + if (!$entity instanceof MylogEntity) { + throw new \Exception("{$uid}에 해당하는 로그를 찾을수 없습니다."); + } + $this->addViewDatas('entity', $entity); + } + protected function modify_process(string $action, $uid): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new MylogDTO($this->request->getPost()); + $entity = $this->service->modify($uid, $dto); + return array($entity, "{$entity->getTitle()} 로그 수정이 완료되었습니다."); + } + protected function view_process($uid): MylogEntity + { + return parent::view_process($uid); + } +} diff --git a/app/Controllers/Admin/TrafficController.php b/app/Controllers/Admin/TrafficController.php index 4699477..4bf4e56 100644 --- a/app/Controllers/Admin/TrafficController.php +++ b/app/Controllers/Admin/TrafficController.php @@ -1,245 +1,58 @@ service === null) { - $this->service = service('serviceService'); + $this->service = service('trafficservice'); } - $this->content_title = lang("{$this->service->getClassPath()}.title"); - $this->class_path .= $this->service->getClassPath(); - $this->uri_path .= strtolower($this->service->getClassPath('/')) . '/'; - // $this->view_path .= strtolower($this->service->getClassPath()) . DIRECTORY_SEPARATOR; + $this->addActionPaths($this::PATH); } - //Index,FieldForm관련 - //생성관련 - public function create_form(): string + //Action작업관련 + protected function create_form_process(string $action): void { - //기본값처리 - $formDatas = []; - $formDatas['location'] = 'chiba'; - $formDatas['rack'] = '100000'; - $formDatas['line'] = '300000'; - $formDatas['type'] = 'normal'; - $formDatas['billing_at'] = date("Y-m-d"); - $formDatas['start_at'] = date("Y-m-d"); - $formDatas['status'] = DEFAULTS['STATUS']; - //viewData처리 - $this->action = __FUNCTION__; - $this->formFields = $this->service->getFormFields(); - $this->formFilters = $this->service->getFormFilters(); - $this->formRules = $this->service->getFormRules(__FUNCTION__); - $this->formOptions = $this->service->getFormOptions(__FUNCTION__); - $this->formDatas = $formDatas; - // dd($this->getViewDatas()); - $view_path = implode(DIRECTORY_SEPARATOR, [ - $this->view_path, - $this->request->getVar('ActionTemplate') ?? 'service', - __FUNCTION__ - ]); - helper(['form', __FUNCTION__]); - return view($view_path, ['viewDatas' => [ - 'control' => $this->getViewDatas(), - 'service' => $this->service, - 'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []] - ]]); + //Form Default값 설정 + $formDatas = []; + $this->addViewDatas('formDatas', $formDatas); + } + protected function create_process(string $action): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new TrafficDTO($this->request->getPost()); + $entity = $this->service->create($dto); + return array($entity, "{$entity->getTitle()} 트래픽정보 생성이 완료되었습니다."); + } + protected function modify_form_process(string $action, $uid): void + { + if (!$uid) { + throw new \Exception("트래픽정보 번호가 정의 되지 않았습니다."); + } + $entity = $this->service->getEntity($uid); + if (!$entity instanceof TrafficEntity) { + throw new \Exception("{$uid}에 해당하는 트래픽정보를 찾을수 없습니다."); + } + $this->addViewDatas('entity', $entity); + } + protected function modify_process(string $action, $uid): array + { + //요청 데이터를 DTO 객체로 변환 + $dto = new TrafficDTO($this->request->getPost()); + $entity = $this->service->modify($uid, $dto); + return array($entity, "{$entity->getTitle()} 트래픽정보 수정이 완료되었습니다."); + } + protected function view_process($uid): TrafficEntity + { + return parent::view_process($uid); } - // public function create(): RedirectResponse|string - // { - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(); - // //전달값정의 - // $this->service->setFormDatas($this->request->getPost()); - // $this->service->setFormFilters(); - // $this->service->setFormRules(); - // $this->doValidations(); - // $context = $this->service->getFormDatas(); - // $runner = new PipelineRunnerService(); - // $runner->addStep(new ServiceRegistration(service('serviceService'))) - // ->addStep(new PaymentRegistrationStep($services['payment'])) - // ->addStep(new LogFinalizationStep()); - // $this->context = $runner->run($context); - // return $this->getResultSuccess(); - // } catch (Throwable $e) { - // return $this->getResultFail($e->getMessage()); - // } - // } - // //수정관련 - // protected function modify_form_process(mixed $entity): ServiceEntity - // { - // $serverEntity = $this->service->getServerService()->getEntity($entity->getServerInfoUID()); - // if (!$serverEntity instanceof ServerEntity) { - // throw new \Exception("[{$entity->getServerInfoUID()}]에 대한 서버정보를 찾을 수 없습니다."); - // } - // $this->serverEntity = $serverEntity; - // return parent::modify_form_process($entity); - // } - // //View 관련 - // protected function view_process(mixed $entity): ServiceEntity - // { - // $serverEntity = $this->service->getServerService()->getEntity($entity->getServerInfoUID()); - // if (!$serverEntity instanceof ServerEntity) { - // throw new \Exception("[{$entity->getServerInfoUID()}]에 대한 서버정보를 찾을 수 없습니다."); - // } - // $this->serverEntity = $serverEntity; - // return parent::view_process($entity); - // } - // //List 관련 - // protected function index_process(array $entities = []): array - // { - // //서비스별 미납 Count - // $this->unPaids = $this->service->getPaymentService()->getUnPaids('serviceinfo_uid'); - // //서비스별 서버리스트 - // $childServers = []; - // foreach ($this->service->getEntities() as $entity) { - // $entities[] = $entity; - // $childServers[$entity->getPK()] = $this->service->getServerService()->getEntities(['serviceinfo_uid' => $entity->getPK()]); - // } - // $this->childServers = $childServers; - // return $entities; - // } - // //대체서버선정 - // public function addServer_form(mixed $uid): RedirectResponse|string - // { - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(['serverinfo_uid']); - // //전달값정의 - // $this->service->setFormDatas($this->request->getGet()); - // $this->service->setFormFilters(); - // $this->service->setFormRules(); - // $this->service->setFormOptions(); - // //기존 Entity 가져오기 - // $entity = $this->service->getEntity($uid); - // if (!$entity instanceof ServiceEntity) { - // throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다."); - // } - // $this->entity = $entity; - // helper(['form']); - // $this->forms = ['attributes' => ['method' => "post",], 'hiddens' => []]; - // return $this->getResultSuccess(); - // } catch (\Exception $e) { - // return $this->getResultFail($e->getMessage()); - // } - // } - // //대체서버 등록 - // public function addServer(int $uid): RedirectResponse|string - // { - // //Transaction Start - // $db = \Config\Database::connect(); - // $db->transStart(); - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(['serverinfo_uid']); - // //전달값정의 - // $this->service->setFormDatas($this->request->getPost()); - // $this->service->setFormFilters(); - // $this->service->setFormRules(); - // $this->doValidations(); - // //기존 Entity 가져오기 - // $entity = $this->service->getEntity($uid); - // if (!$entity instanceof ServiceEntity) { - // throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다."); - // } - // $this->entity = $this->service->addeAlternativeServer($entity, $this->service->getFormDatas()); - // $db->transCommit(); - // return $this->getResultSuccess('대체서버 추가가 완료되었습니다.'); - // } catch (\Exception $e) { - // $db->transRollback(); - // return $this->getResultFail($e->getMessage()); - // } - // } - // //대체서버를 MAIN서버로 설정 - // public function changeServer(mixed $uid): RedirectResponse|string - // { - // //Transaction Start - // $db = \Config\Database::connect(); - // $db->transStart(); - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(['serverinfo_uid']); - // //전달값정의 - // $this->service->setFormDatas($this->request->getGet()); - // $this->service->setFormFilters(); - // $this->service->setFormRules(); - // $this->doValidations(); - // //기존 Entity 가져오기 - // $entity = $this->service->getEntity($uid); - // if (!$entity instanceof ServiceEntity) { - // throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다."); - // } - // //서버정보설정 - // $this->service->replaceMainServer($entity, $this->service->getFormDatas()); - // $db->transCommit(); - // return $this->getResultSuccess('메인서버 설정이 바뀌었습니다.'); - // } catch (\Exception $e) { - // $db->transRollback(); - // return $this->getResultFail($e->getMessage()); - // } - // } - // //서비스 서버해지 - // public function terminateServer(mixed $uid): RedirectResponse|string - // { - // //Transaction Start - // $db = \Config\Database::connect(); - // $db->transStart(); - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(['serverinfo_uid']); - // //전달값정의 - // $this->service->setFormDatas($this->request->getGet()); - // //기존 Entity 가져오기 - // $entity = $this->service->getEntity($uid); - // if (!$entity instanceof ServiceEntity) { - // throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다."); - // } - // $formDatas = $this->service->getFormDatas(); - // $this->service->terminateServer($entity, $formDatas); - // $db->transCommit(); - // return $this->getResultSuccess('서버해지가 완료되었습니다.'); - // } catch (\Exception $e) { - // $db->transRollback(); - // return $this->getResultFail($e->getMessage()); - // } - // } - // public function history(int $uid): RedirectResponse|string - // { - // //Transaction Start - // $db = \Config\Database::connect(); - // $db->transStart(); - // try { - // $this->service->setAction(__FUNCTION__); - // $this->service->setFormFields(['history']); - // $this->service->setFormFilters(); - // $this->service->setFormRules(); - // //전달값정의 - // $this->service->setFormDatas($this->request->getPost()); - // $this->doValidations(); - // //기존 Entity 가져오기 - // $entity = $this->service->getEntity($uid); - // if (!$entity instanceof ServiceEntity) { - // throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다."); - // } - // $this->entity = $this->service->history($entity, $this->service->getFormDatas()); - // $db->transCommit(); - // return $this->getResultSuccess('서비스 비고가 수정되었습니다.'); - // } catch (\Exception $e) { - // $db->transRollback(); - // return $this->getResultFail($e->getMessage()); - // } - // } } diff --git a/app/Controllers/Admin/UserController.php b/app/Controllers/Admin/UserController.php index 093270b..1adc874 100644 --- a/app/Controllers/Admin/UserController.php +++ b/app/Controllers/Admin/UserController.php @@ -4,7 +4,6 @@ namespace App\Controllers\Admin; use App\DTOs\UserDTO; use App\Entities\UserEntity; -use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use Psr\Log\LoggerInterface; @@ -36,13 +35,12 @@ class UserController extends AdminController $formDatas = ['role' => [ROLE['USER']['MANAGER']]]; $this->addViewDatas('formDatas', $formDatas); } - protected function create_process(string $action): string|RedirectResponse + protected function create_process(string $action): array { //요청 데이터를 DTO 객체로 변환 $dto = new UserDTO($this->request->getPost()); $entity = $this->service->create($dto); - $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); - return redirect()->to($redirect_url)->with('message', "{$entity->getTitle()} 계정 생성이 완료되었습니다."); + return array($entity, "{$entity->getTitle()} 계정 생성이 완료되었습니다."); } protected function modify_form_process(string $action, $uid): void { @@ -55,14 +53,12 @@ class UserController extends AdminController } $this->addViewDatas('entity', $entity); } - protected function modify_process(string $action, $uid): string|RedirectResponse + protected function modify_process(string $action, $uid): array { - //요청 데이터를 DTO 객체로 변환 $dto = new UserDTO($this->request->getPost()); $entity = $this->service->modify($uid, $dto); - $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); - return redirect()->to($redirect_url)->with('message', "{$entity->getTitle()} 계정 수정이 완료되었습니다."); + return array($entity, "{$entity->getTitle()} 계정 수정이 완료되었습니다."); } protected function view_process($uid): UserEntity { diff --git a/app/Controllers/CommonController.php b/app/Controllers/CommonController.php index 742958d..766a3c9 100644 --- a/app/Controllers/CommonController.php +++ b/app/Controllers/CommonController.php @@ -74,9 +74,35 @@ abstract class CommonController extends BaseController $this->addViewDatas('authContext', $this->getAuthContext()); $this->addViewDatas('classPath', $this->service->getClassPaths(false)); } - protected function action_rediect_process(string $message): RedirectResponse + protected function action_modal_process(string $message): string + { + return " + + "; + } + protected function action_redirect_process(string $redirect_url, string $message): RedirectResponse { - $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); return redirect()->to($redirect_url)->with('message', $message); } protected function action_render_process(array $view_paths, string $view_file, array $viewDatas): string diff --git a/app/DTOs/CollectorDTO.php b/app/DTOs/CollectorDTO.php new file mode 100644 index 0000000..f4d33dc --- /dev/null +++ b/app/DTOs/CollectorDTO.php @@ -0,0 +1,31 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + public function toArray(): array + { + return [ + 'uid' => $this->uid, + 'trafficinfo_uid' => $this->trafficinfo_uid, + 'in' => $this->in, + 'out' => $this->out, + ]; + } +} diff --git a/app/DTOs/MylogDTO.php b/app/DTOs/MylogDTO.php new file mode 100644 index 0000000..d83e9e7 --- /dev/null +++ b/app/DTOs/MylogDTO.php @@ -0,0 +1,29 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + public function toArray(): array + { + return [ + 'uid' => $this->uid, + 'title' => $this->title, + 'content' => $this->content, + ]; + } +} diff --git a/app/DTOs/TrafficDTO.php b/app/DTOs/TrafficDTO.php new file mode 100644 index 0000000..d453cec --- /dev/null +++ b/app/DTOs/TrafficDTO.php @@ -0,0 +1,35 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + public function toArray(): array + { + return [ + 'uid' => $this->uid, + 'client' => $this->client, + 'switch' => $this->switch, + 'ip' => $this->ip, + 'interface' => $this->interface, + 'status' => $this->status, + ]; + } +} diff --git a/app/Database/traffic_test1.sql b/app/Database/traffic_test1.sql new file mode 100644 index 0000000..284b11d --- /dev/null +++ b/app/Database/traffic_test1.sql @@ -0,0 +1,119 @@ +-- MySQL dump 10.19 Distrib 10.3.28-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: traffic +-- ------------------------------------------------------ +-- Server version 10.3.28-MariaDB-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `mylog` +-- + +DROP TABLE IF EXISTS `mylog`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `mylog` ( + `uid` int(11) NOT NULL AUTO_INCREMENT, + `title` varchar(255) NOT NULL, + `context` text DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='로그정보'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `mylog` +-- + +LOCK TABLES `mylog` WRITE; +/*!40000 ALTER TABLE `mylog` DISABLE KEYS */; +/*!40000 ALTER TABLE `mylog` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `trafficinfo` +-- + +DROP TABLE IF EXISTS `trafficinfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `trafficinfo` ( + `uid` int(11) NOT NULL AUTO_INCREMENT, + `client` varchar(50) NOT NULL, + `switch` varchar(10) NOT NULL, + `ip` char(16) NOT NULL, + `interface` varchar(20) NOT NULL, + `status` varchar(20) NOT NULL DEFAULT 'available', + `updated_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='트래픽정보'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `trafficinfo` +-- + +LOCK TABLES `trafficinfo` WRITE; +/*!40000 ALTER TABLE `trafficinfo` DISABLE KEYS */; +/*!40000 ALTER TABLE `trafficinfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `uid` int(11) NOT NULL AUTO_INCREMENT, + `id` varchar(20) NOT NULL, + `passwd` varchar(255) NOT NULL, + `name` varchar(20) NOT NULL, + `email` varchar(50) NOT NULL, + `mobile` varchar(20) DEFAULT NULL, + `role` varchar(255) DEFAULT NULL, + `status` varchar(20) DEFAULT 'normal', + `updated_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`uid`), + UNIQUE KEY `UQ_id` (`id`), + UNIQUE KEY `UQ_email` (`email`) +) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8 COMMENT='관리자정보'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES (1,'choi.jh','$2y$10$.vl2FtwJsjMNFCJJm3ISDu7m3vBB85mZ5fRQxcfI0uK/2D1e8Xora','최준흠','choi.jh@prime-idc.jp','0434434327','manager,cloudflare,security,director,master','available','2025-10-02 08:12:39','2023-03-23 06:50:04',NULL),(2,'cho.jh','$2y$10$ot/aUXR/W1n4Q3dZA2dZCOxQrpVb2Bq31Y7xFQS3G6D1gtImmyBjm','조준희','cho.jh@prime-idc.jp','','manager,cloudflare,security','available','2025-10-02 08:12:46','2023-03-24 02:20:48',NULL),(4,'kimdy','$2y$10$18uyn94xdprzAnt.oYZ5weAvb8rRLhkz/SdQrjEK7yuGhCr9PlUCC','김동윤','kimdy@prime-idc.jp','','manager,cloudflare,security','available','2025-10-02 08:12:51','2023-03-24 02:21:50',NULL),(5,'kimhy','$2y$10$.yEKVqY.F7HoSOZijl4uyeulUtfAQ4EDRiyR2JpgFYBuKw.mZoZvG','김효영','khy@prime-idc.jp',NULL,'manager,security,director','available','2025-06-24 01:11:41','2023-03-24 02:23:18',NULL),(6,'kim.eh','$2y$10$YmwicI.Br4XNyGamfRADMOu.qlkwKd2fmnNkL7YIkNHGndvqYPnCq','김은혁','kim.eh@prime-idc.jp',NULL,'manager,cloudflare,security','available','2025-06-24 01:09:38','2023-03-24 02:23:52',NULL),(7,'leeph','$2y$10$lR739WzJsW6rDLgchYs7buek4BYeTlKHTQY60RDqRms9Io7RSY3AC','이풍호','leeph@prime-idc.jp','','manager,cloudflare,security','available','2025-10-02 08:13:18','2023-03-24 02:24:21',NULL),(8,'jinmingyu','$2y$10$PI8WA6d/z4hDE6hxJoUhbuMH3vTTWH0Ry2Z6fTLUUpwQGaE/9bEZa','김명옥','jinmingyu@idcjp.jp',NULL,'manager,cloudflare,security','available','2025-06-24 01:09:47','2023-03-24 02:25:00',NULL),(9,'kangdh','$2y$10$gu9OS2DDQQ5H.Hh61t3BSOUp87l35q.xsduVSxvCcn8IgA4jrATgG','강동헌','kang.dh@idcjp.jp','','manager,cloudflare,security','available','2025-10-02 08:13:26','2023-03-24 02:25:48',NULL),(10,'yoohs','$2y$10$TGASk98FuZ6Ux6FDquu1aO3rztA01MCle/Vs1.3iaEMQzakAbCzJy','유혜성','yoo.hs@idcjp.jp','','manager,cloudflare,security','available','2025-10-02 08:13:33','2023-03-24 02:26:31',NULL),(11,'kim.yh','$2y$10$8GciQXpKYiR3TDWQfh9JjOQAQ.YWGoOSCL0a0/w4XACO0mUgjjbWy','김영환','kim.yh@idcjp.jp','','manager,cloudflare,security','available','2025-10-02 08:13:39','2023-03-24 02:27:05',NULL),(12,'yunmuj','$2y$10$zkgwGVj2JSOVIsxLe8fePe1gvWWaCemfZMktzBlrN8oLb3CKydkZC','윤무정','yunmuj@idcjp.jp','','manager,cloudflare,security','available','2025-10-02 08:13:50','2023-03-24 02:27:59',NULL),(13,'kim.mt','$2y$10$3dfkA0oq4LqiJOmjbBGKe.p0Dhj/MDqjoTdw11BOPF/H2qJqnEuHO','김문태','kim.mt@idcjp.jp','','manager,cloudflare,security','available','2025-10-02 08:13:56','2023-03-24 02:28:31',NULL),(14,'shin.ms','$2y$10$.jaDkGtm/gZK3ZDF.fJUGOwMI7Zif5588X5AxSMvvk238RDI7spQ6','신민수','shin.ms@idcjp.jp','','manager,cloudflare','terminated','2025-10-02 08:11:11','2023-03-24 02:29:00',NULL),(15,'park.sm','$2y$10$RgDY4f9kuryRNDJVJU5pn.JV.38ZWA9UTgmONBlP74WwIqamMbnY2','박선미','park.sm@idcjp.jp','','manager,cloudflare,security','available','2025-10-13 05:24:59','2023-03-24 02:29:34',NULL),(24,'kobn','$2y$10$pWM/XFfSNeSng32sypbDX.WaR4UlM4EDkYKCQfFkYIOC7Ppg0nc5G','고병남','ko@prime-idc.jp',NULL,'manager,cloudflare,security','available','2025-06-24 01:10:02','2024-10-29 06:30:19',NULL),(25,'jeong.sg','$2y$10$OzH6140JztiUEs4s/VHbPOxfxubFooqwqVhGpdFG8OJCGAFXNu546','정상구','jeong.sg@prime-idc.jp','','manager,cloudflare,security','available','2025-10-02 08:14:21','2025-01-23 00:29:46',NULL),(43,'test1234','$2y$10$y47tGsZ7YTta16nD.wPtkuS./9EjeNQYAjVhsZR448.sL..dHFBsK','test1234','test@gmail.com','0434434327','manager,cloudflare','available','2025-10-21 01:00:16','2025-07-01 06:05:11',NULL),(44,'test333','$2y$10$h7dD8XYN9osH2pzxP7lqdeOrQJQ12d.WK6Yp1WUx7139VUx8IQrba','test333','test2333@co.kr22','2343422','manager','available','2025-10-21 01:00:51','2025-07-11 07:23:13',NULL),(45,'kim.jh','$2y$10$voCle9yFWWhGhQ0JrH46puLYySJYq6O41/BSrKxx0MHWyO8KDf97u','김준한','kim.jh@prime-idc.jp','','manager,cloudflare,security','available','2025-10-02 08:14:32','2025-08-08 02:27:49',NULL),(52,'test3334455','$2y$10$V6A9.tYyu2QKcWIJ0y5vR.hZ8vtHRa6u.GWoUehmfnInfmTBLtivC','test333444555','test2333@co.kr44455','234342244455','manager,cloudflare','available','2025-10-21 01:00:51','2025-11-10 02:41:52',NULL); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2025-11-10 14:43:07 diff --git a/app/Entities/CollectorEntity.php b/app/Entities/CollectorEntity.php new file mode 100644 index 0000000..dd41dfc --- /dev/null +++ b/app/Entities/CollectorEntity.php @@ -0,0 +1,12 @@ +attributes['user_uid'] ?? null; - } //기본기능용 - public function getCustomTitle(mixed $title = null): string - { - return $this->getTitle(); - } } diff --git a/app/Forms/CollectorForm.php b/app/Forms/CollectorForm.php new file mode 100644 index 0000000..3809c66 --- /dev/null +++ b/app/Forms/CollectorForm.php @@ -0,0 +1,92 @@ + lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"]; + foreach (service('trafficservice')->getEntities() as $entity) { + $tempOptions[$entity->getPK()] = $entity->getTitle(); + } + $options[$field]['options'] = $tempOptions; + $options[$field]['extras'] = ['class' => 'select-field']; + break; + default: + $options = parent::getFormOption($action, $field, $options); + break; + } + return $options; + } +} diff --git a/app/Forms/CommonForm.php b/app/Forms/CommonForm.php index 414cd4c..1b4795e 100644 --- a/app/Forms/CommonForm.php +++ b/app/Forms/CommonForm.php @@ -98,9 +98,16 @@ abstract class CommonForm { switch ($field) { case 'user_uid': + $tempOptions = ['' => lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"]; + foreach (service('userservice')->getEntities() as $entity) { + $tempOptions[$entity->getPK()] = $entity->getTitle(); + } + $options[$field]['options'] = $tempOptions; + $options[$field]['extras'] = ['class' => 'select-field']; + break; case 'clientinfo_uid': $tempOptions = ['' => lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"]; - foreach (service('UserService')->getEntities() as $entity) { + foreach (service('clientervice')->getEntities() as $entity) { $tempOptions[$entity->getPK()] = $entity->getTitle(); } $options[$field]['options'] = $tempOptions; diff --git a/app/Forms/MylogForm.php b/app/Forms/MylogForm.php new file mode 100644 index 0000000..acaef0e --- /dev/null +++ b/app/Forms/MylogForm.php @@ -0,0 +1,67 @@ +getAttribute('table')}.{$field}]" : ""; + $rules[$field] = $rule; + break; + case "ip": + $rule = "required|trim|valid_ip[both]"; //ipv4 , ipv6 , both(ipv4,ipv6) + $rules[$field] = $rule; + break; + case "interface": + $rule = "required|trim|string"; + $rules[$field] = $rule; + break; + case "status": + $rule = "required|trim|string"; + $rules[$field] = $rule; + break; + default: + $rules = parent::getFormRule($action, $field, $rules); + break; + } + return $rules; } } diff --git a/app/Helpers/CollectorHelper.php b/app/Helpers/CollectorHelper.php new file mode 100644 index 0000000..cd8b7c7 --- /dev/null +++ b/app/Helpers/CollectorHelper.php @@ -0,0 +1,13 @@ +form_dropdown_common($field, $value, $viewDatas, $extras); - break; - case 'serverinfo_uid': - $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field'; - $attributes = ['data-price' => 'price']; - $form = $this->form_dropdown_common($field, $value, $viewDatas, $extras, $attributes); - break; - case 'amount': - $form = form_input($field, 0, ["readonly" => "readonly", ...$extras]); - break; - default: - $form = parent::getFieldForm($field, $value, $viewDatas, $extras); - break; - } - return $form; - } - public function getFieldView(string $field, mixed $value, array $viewDatas, array $extras = []): string|null - { - switch ($field) { - case 'amount': - case 'sale': - $value = number_format($value) . "원"; - break; - case 'billing_at': - if (array_key_exists('unPaids', $viewDatas)) { - if (array_key_exists($viewDatas['entity']->getPK(), $viewDatas['unPaids'])) { - $value .= sprintf( - "
%s개,총 %s원
", - $viewDatas['entity']->getPK(), - $viewDatas['unPaids'][$viewDatas['entity']->getPK()]['cnt'], - number_format($viewDatas['unPaids'][$viewDatas['entity']->getPK()]['amount']) - ); - } - } - break; - default: - $value = parent::getFieldView($field, $value, $viewDatas, $extras); - break; - } - if (is_array($value)) { - throw new \Exception(__METHOD__ . "에서 오류: {$field}의 값이 Array형태입니다"); - } - return $value; - } - - public function getListButton(string $action, string $label, array $viewDatas, array $extras = []): string - { - switch ($action) { - case 'modify': - $action = parent::getListButton($action, $label, $viewDatas, $extras); - break; - case 'addServer': - $action = form_label( - $label ? $label : ICONS['REBOOT'], - $action, - [ - "data-src" => "/admin/customer/service/addServer/{$viewDatas['entity']->getPK()}", - "data-bs-toggle" => "modal", - "data-bs-target" => "#modal_action_form", - "class" => "btn btn-sm form-label-sm", - ...$extras - ] - ); - break; - case 'onetime': - $action = form_label( - $label ? $label : ICONS['ONETIME'], - $action, - [ - "data-src" => "/admin/customer/payment/create?serviceinfo_uid={$viewDatas['entity']->getPK()}", - "data-bs-toggle" => "modal", - "data-bs-target" => "#modal_action_form", - "class" => "btn btn-sm form-label-sm", - ...$extras - ] - ); - break; - case 'history': - $action = form_label( - $label ? $label : ICONS['HISTORY'], - $action, - [ - "data-src" => "/admin/customer/service/history?serviceinfo_uid={$viewDatas['entity']->getPK()}&serviceinfo_uid={$viewDatas['entity']->getPK()}&ActionTemplate=popup", - "data-bs-toggle" => "modal", - "data-bs-target" => "#modal_action_form", - "class" => "btn btn-sm btn-primary form-label-sm", - ...$extras - ] - ); - break; - default: - $action = parent::getListButton($action, $label, $viewDatas, $extras); - break; - } - return $action; - } } diff --git a/app/Language/en/Collector.php b/app/Language/en/Collector.php new file mode 100644 index 0000000..ace697d --- /dev/null +++ b/app/Language/en/Collector.php @@ -0,0 +1,12 @@ + "수집정보", + 'label' => [ + 'trafficinfo_uid' => "고객명", + 'in' => "IN", + 'out' => "OUT", + 'updated_at' => "수정일", + 'created_at' => "생성일", + 'deleted_at' => "삭제일", + ], +]; diff --git a/app/Language/en/Mylog.php b/app/Language/en/Mylog.php new file mode 100644 index 0000000..7326bad --- /dev/null +++ b/app/Language/en/Mylog.php @@ -0,0 +1,12 @@ + "작업Log", + 'label' => [ + 'uid' => "번호", + 'title' => "제목", + 'content' => "내용", + 'updated_at' => "수정일", + 'created_at' => "작성일", + 'deleted_at' => "삭제일", + ], +]; diff --git a/app/Language/en/Traffic.php b/app/Language/en/Traffic.php index 69742f6..5522741 100644 --- a/app/Language/en/Traffic.php +++ b/app/Language/en/Traffic.php @@ -1,45 +1,16 @@ "서비스정보", + 'title' => "트래픽정보", 'label' => [ - 'user_uid' => "관리자", - 'clientinfo_uid' => "고객", - 'serverinfo_uid' => "서버", - 'site' => "사이트", - 'code' => "코드", - 'title' => "서비스명", - 'location' => "위치", - 'rack' => "상면비", - 'line' => "회선비", - 'billing_at' => "결제일", - 'sale' => "할인액", - 'amount' => "월청구액", - 'start_at' => "시작일", - 'end_at' => "해지일", - 'history' => "사용이력", + 'client' => "고객명", + 'switch' => "스위치", + 'ip' => "IP", + 'interface' => "인텍스", 'status' => "상태", 'updated_at' => "수정일", - 'created_at' => "신청일", + 'created_at' => "생성일", 'deleted_at' => "삭제일", ], - "SITE" => SITES, - "LOCATION" => [ - "chiba" => "치바", - "tokyo" => "도쿄", - "3center" => "3센터", - ], - - "RACK" => [ - "0" => "0원", - "100000" => "10만원", - "200000" => "20만원", - "300000" => "30만원", - ], - "LINE" => [ - "0" => "0원", - "300000" => "30만원", - "500000" => "50만원", - ], "STATUS" => [ STATUS['AVAILABLE'] => "사용중", STATUS['PAUSE'] => "일시정지", diff --git a/app/Libraries/LogCollector.php b/app/Libraries/LogCollector.php deleted file mode 100644 index 72817b4..0000000 --- a/app/Libraries/LogCollector.php +++ /dev/null @@ -1,39 +0,0 @@ -addClassPaths('Collector'); + } + public function getFormService(): CollectorForm + { + if ($this->formServiceInstance === null) { + $this->formServiceInstance = new CollectorForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->formServiceInstance; + } + public function getHelper(): CollectorHelper + { + if ($this->helperInstance === null) { + $this->helperInstance = new CollectorHelper(); + $this->helperInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->helperInstance; + } + //기본 기능부분 + protected function create_process(array $formDatas): CollectorEntity + { + //CollectorEntity를 생성하면 Setter가 자동 호출됩니다. + return new CollectorEntity($formDatas); + } + public function create(object $dto): CollectorEntity + { + if (!$dto instanceof CollectorDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::create($dto); + } + protected function modify_process($uid, array $formDatas): CollectorEntity + { + if (!$uid) { + throw new \Exception("수집 번호가 정의 되지 않았습니다."); + } + $entity = $this->getEntity($uid); + if (!$entity instanceof CollectorEntity) { + throw new \Exception("{$uid}에 해당하는 수집정보을 찾을수 없습니다."); + } + // 변경 사항을 Entity에 적용합니다. (Dirty Tracking 활성화) + $formDatas[$this->model->getPKField()] = $uid; + $entity->fill($formDatas); + // 💡 부모 호출 제거: 변경된 Entity 객체를 반환합니다. + return $entity; + } + public function modify($uid, object $dto): CollectorEntity + { + if (!$dto instanceof CollectorDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::modify($uid, $dto); + } + //List 검색용 + //FormFilter 조건절 처리 + //검색어조건절처리 + public function setSearchWord(string $word): void + { + $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both'); + parent::setSearchWord($word); + } + + /** + * SNMP GET 요청을 실행하고 Octet 값을 추출합니다. + * @param string $ip 장비 IP + * @param int $ifIndex 인터페이스 인덱스 + * @param string $community SNMP 커뮤니티 문자열 + * @param string $oid OID (접두사) + * @return int|null 수집된 Octet 값 또는 오류 시 null + */ + protected function getOctets(string $ip, int $ifIndex, string $community, string $oid): ?int + { + $fullOid = $oid . $ifIndex; + // snmp2_get을 사용하여 SNMP v2c로 요청 (64비트 카운터 지원에 유리) + $result = @snmp2_get($ip, $community, $fullOid, 100000, 3); // 3초 타임아웃 + if ($result === false || $result === null) { + log_message('error', "SNMP 통신 실패: {$ip} ({$fullOid}, Community: {$community})"); + return null; + } + // 결과 문자열에서 숫자 값만 추출하여 정수로 변환 + if (preg_match('/\d+/', $result, $matches)) { + return (int)$matches[0]; + } + return null; + } + /** + * 트래픽을 수집하고 Kbit/s를 계산하여 DB에 저장합니다. + * @param int $trafficInfoUid traffic_info 테이블의 기본 키 (연계 키) + * @param string $ip 장비 IP + * @param int $ifIndex 인터페이스 인덱스 + * @param string $community SNMP 커뮤니티 문자열 + */ + public function collectAndCalculate(int $trafficInfoUid, string $ip, int $ifIndex, string $community): void + { + $currentInOctets = $this->getOctets($ip, $ifIndex, $community, self::OID_IF_IN_OCTETS); + $currentOutOctets = $this->getOctets($ip, $ifIndex, $community, self::OID_IF_OUT_OCTETS); + $currentTime = Time::now()->toDateTimeString(); + if ($currentInOctets === null || $currentOutOctets === null) { + log_message('warning', "트래픽 수집 실패: {$ip} - IF{$ifIndex} (UID: {$trafficInfoUid})"); + return; + } + // 이전 데이터를 조회하여 Rate 계산에 사용 + $lastEntry = $this->model->getLastEntryByInfoUid($trafficInfoUid); + $inKbitsSec = 0.0; + $outKbitsSec = 0.0; + // 이전 데이터가 있어야만 Rate 계산 가능 + if ($lastEntry !== null) { + $lastTime = Time::parse($lastEntry['created_at'])->getTimestamp(); + $deltaTime = Time::now()->getTimestamp() - $lastTime; + + if ($deltaTime > 0) { + // Raw Octets 값의 차분 계산 + $deltaInOctets = $currentInOctets - $lastEntry['raw_in_octets']; + $deltaOutOctets = $currentOutOctets - $lastEntry['raw_out_octets']; + + // Kbit/s 계산: (Delta_Octets * 8 bits) / Delta_Time_Seconds / 1000 (-> Kbit/s) + $inKbitsSec = ($deltaInOctets * 8) / $deltaTime / 1000; + $outKbitsSec = ($deltaOutOctets * 8) / $deltaTime / 1000; + } else { + log_message('error', "시간 차이 오류 발생: {$ip} - {$deltaTime}초 (UID: {$trafficInfoUid})"); + } + } + + // Collector DB에 결과 저장 + $this->model->insert([ + 'trafficinfo_uid' => $trafficInfoUid, + 'in_kbits_sec' => round($inKbitsSec, 2), + 'out_kbits_sec' => round($outKbitsSec, 2), + 'raw_in_octets' => $currentInOctets, // 다음 계산을 위해 Raw 값 저장 + 'raw_out_octets' => $currentOutOctets, // 다음 계산을 위해 Raw 값 저장 + 'created_at' => $currentTime, + ]); + log_message('info', "트래픽 계산 및 저장 완료 (UID: {$trafficInfoUid}), In: {$inKbitsSec} Kb/s"); + } +} diff --git a/app/Services/CommonService.php b/app/Services/CommonService.php index b7b503b..2768fbf 100644 --- a/app/Services/CommonService.php +++ b/app/Services/CommonService.php @@ -50,9 +50,7 @@ abstract class CommonService { try { $entities = $this->getEntities_process($where, $columns); - echo "

test

"; - echo "

test

"; - echo static::class . DIRECTORY_SEPARATOR . __FUNCTION__ . " Query:" . $this->model->getLastQuery(); + // echo static::class . DIRECTORY_SEPARATOR . __FUNCTION__ . " Query:" . $this->model->getLastQuery(); return $entities; } catch (\Exception $e) { $message = sprintf( diff --git a/app/Services/MylogService.php b/app/Services/MylogService.php new file mode 100644 index 0000000..30bd4c1 --- /dev/null +++ b/app/Services/MylogService.php @@ -0,0 +1,82 @@ +addClassPaths('Mylog'); + } + public function getFormService(): MylogForm + { + if ($this->formServiceInstance === null) { + $this->formServiceInstance = new MylogForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->formServiceInstance; + } + public function getHelper(): MylogHelper + { + if ($this->helperInstance === null) { + $this->helperInstance = new MylogHelper(); + $this->helperInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->helperInstance; + } + //기본 기능부분 + protected function create_process(array $formDatas): MylogEntity + { + //MylogEntity를 생성하면 Setter가 자동 호출됩니다. + return new MylogEntity($formDatas); + } + public function create(object $dto): MylogEntity + { + if (!$dto instanceof MylogDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::create($dto); + } + protected function modify_process($uid, array $formDatas): MyLogEntity + { + if (!$uid) { + throw new \Exception("로그 번호가 정의 되지 않았습니다."); + } + $entity = $this->getEntity($uid); + if (!$entity instanceof MyLogEntity) { + throw new \Exception("{$uid}에 해당하는 계정을 찾을수 없습니다."); + } + // 변경 사항을 Entity에 적용합니다. (Dirty Tracking 활성화) + $formDatas[$this->model->getPKField()] = $uid; + $entity->fill($formDatas); + // 💡 부모 호출 제거: 변경된 Entity 객체를 반환합니다. + return $entity; + } + public function modify($uid, object $dto): MyLogEntity + { + if (!$dto instanceof MylogDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::create($dto); + } +} diff --git a/app/Services/TrafficService.php b/app/Services/TrafficService.php index 77ece4c..68db92e 100644 --- a/app/Services/TrafficService.php +++ b/app/Services/TrafficService.php @@ -2,17 +2,17 @@ namespace App\Services; +use App\DTOs\TrafficDTO; use App\Entities\TrafficEntity; use App\Forms\TrafficForm; +use App\Helpers\TrafficHelper; use App\Models\TrafficModel; -use DateTimeImmutable; -use DateTimeZone; +use RuntimeException; class TrafficService extends CommonService { - public function __construct( - TrafficModel $model, - ) { + public function __construct(TrafficModel $model) + { parent::__construct($model); $this->addClassPaths('Traffic'); } @@ -44,26 +44,47 @@ class TrafficService extends CommonService } return $this->helperInstance; } - //필수함수 - // public function getNewServiceEntities(int $interval, string $status = DEFAULTS['STATUS']): array - // { - // return $this->getEntities(sprintf("start_at >= NOW()-INTERVAL {$interval} DAY AND status = '%s'", $status)); - // } - // //서비스별 총 금액 - // public function getTotalAmounts($where = []): array - // { - // $rows = $this->model->groupBy('clientinfo_uid')->select("clientinfo_uid,SUM(amount) AS amount") - // ->where($where) - // ->get()->getResult(); - // $amounts = []; - // foreach ($rows as $row) { - // $amounts[$row->clientinfo_uid] = $row->amount; - // } - // return $amounts; - // } - // public function registerServiceAndGetId(array $context): array - // { - // $this->model->create($context); - // return $context; - // } + //기본 기능부분 + protected function create_process(array $formDatas): TrafficEntity + { + //TrafficEntity를 생성하면 Setter가 자동 호출됩니다. + return new TrafficEntity($formDatas); + } + public function create(object $dto): TrafficEntity + { + if (!$dto instanceof TrafficDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::create($dto); + } + protected function modify_process($uid, array $formDatas): TrafficEntity + { + if (!$uid) { + throw new \Exception("트래픽 번호가 정의 되지 않았습니다."); + } + $entity = $this->getEntity($uid); + if (!$entity instanceof TrafficEntity) { + throw new \Exception("{$uid}에 해당하는 트래픽정보을 찾을수 없습니다."); + } + // 변경 사항을 Entity에 적용합니다. (Dirty Tracking 활성화) + $formDatas[$this->model->getPKField()] = $uid; + $entity->fill($formDatas); + // 💡 부모 호출 제거: 변경된 Entity 객체를 반환합니다. + return $entity; + } + public function modify($uid, object $dto): TrafficEntity + { + if (!$dto instanceof TrafficDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); + } + return parent::modify($uid, $dto); + } + //List 검색용 + //FormFilter 조건절 처리 + //검색어조건절처리 + public function setSearchWord(string $word): void + { + $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both'); + parent::setSearchWord($word); + } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 61718cd..a76f3b3 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -3,7 +3,6 @@ namespace App\Services; use App\DTOs\UserDTO; -use App\Entities\CommonEntity; use App\Entities\UserEntity; use App\Forms\UserForm; use App\Helpers\UserHelper; @@ -74,6 +73,7 @@ class UserService extends CommonService unset($formDatas['confirmpassword']); } // 변경 사항을 Entity에 적용합니다. (Dirty Tracking 활성화) + $formDatas[$this->model->getPKField()] = $uid; $entity->fill($formDatas); // 💡 부모 호출 제거: 변경된 Entity 객체를 반환합니다. return $entity; diff --git a/app/Views/admin/collector/create_form.php b/app/Views/admin/collector/create_form.php new file mode 100644 index 0000000..82d4599 --- /dev/null +++ b/app/Views/admin/collector/create_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['formDatas'][$field] ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/collector/download.php b/app/Views/admin/collector/download.php new file mode 100644 index 0000000..c835c18 --- /dev/null +++ b/app/Views/admin/collector/download.php @@ -0,0 +1,19 @@ + + + + $label): ?> + + + + + + + + + + + + + + +
getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?>
\ No newline at end of file diff --git a/app/Views/admin/collector/index.php b/app/Views/admin/collector/index.php new file mode 100644 index 0000000..80d0a62 --- /dev/null +++ b/app/Views/admin/collector/index.php @@ -0,0 +1,59 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> + +section('content') ?> +
include("{$layouts['path']}/top"); ?>
+ + + + + +
include("{$layouts['path']}/left_menu"); ?> +
include("{$template}/index_header"); ?>
+
+ +
+ include("{$template}/index_content_filter"); ?> + 'batchjob_form', 'method' => "post"]) ?> + + + + + $label): ?> + + + + + + + + + getStatus() === DEFAULTS['STATUS']; + $rowClass = $isDefaultStatus ? "" : 'class="table-danger"'; + $num = $viewDatas['index_totalcount'] - (($viewDatas['page'] - 1) * $viewDatas['perpage'] + $cnt); + ?> + > + + $label): ?> + + + + + +
번호getListLabel($field, $label, $viewDatas) ?>작업
getListButton('modify', $num, $viewDatas) ?>getFieldView($field, $entity->$field, $viewDatas) ?> + getListButton('view', '', $viewDatas) ?>  + getListButton('delete', '', $viewDatas) ?> +
+ include("{$template}/index_content_bottom"); ?> + +
+
+ +
+
include("{$layouts['path']}/bottom"); ?>
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/collector/modify_form.php b/app/Views/admin/collector/modify_form.php new file mode 100644 index 0000000..040274f --- /dev/null +++ b/app/Views/admin/collector/modify_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/collector/view.php b/app/Views/admin/collector/view.php new file mode 100644 index 0000000..80061d8 --- /dev/null +++ b/app/Views/admin/collector/view.php @@ -0,0 +1,17 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?>getFieldView($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?>
+
+
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/mylog/create_form.php b/app/Views/admin/mylog/create_form.php new file mode 100644 index 0000000..82d4599 --- /dev/null +++ b/app/Views/admin/mylog/create_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['formDatas'][$field] ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/mylog/download.php b/app/Views/admin/mylog/download.php new file mode 100644 index 0000000..c835c18 --- /dev/null +++ b/app/Views/admin/mylog/download.php @@ -0,0 +1,19 @@ + + + + $label): ?> + + + + + + + + + + + + + + +
getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?>
\ No newline at end of file diff --git a/app/Views/admin/mylog/index.php b/app/Views/admin/mylog/index.php new file mode 100644 index 0000000..80d0a62 --- /dev/null +++ b/app/Views/admin/mylog/index.php @@ -0,0 +1,59 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> + +section('content') ?> +
include("{$layouts['path']}/top"); ?>
+ + + + + +
include("{$layouts['path']}/left_menu"); ?> +
include("{$template}/index_header"); ?>
+
+ +
+ include("{$template}/index_content_filter"); ?> + 'batchjob_form', 'method' => "post"]) ?> + + + + + $label): ?> + + + + + + + + + getStatus() === DEFAULTS['STATUS']; + $rowClass = $isDefaultStatus ? "" : 'class="table-danger"'; + $num = $viewDatas['index_totalcount'] - (($viewDatas['page'] - 1) * $viewDatas['perpage'] + $cnt); + ?> + > + + $label): ?> + + + + + +
번호getListLabel($field, $label, $viewDatas) ?>작업
getListButton('modify', $num, $viewDatas) ?>getFieldView($field, $entity->$field, $viewDatas) ?> + getListButton('view', '', $viewDatas) ?>  + getListButton('delete', '', $viewDatas) ?> +
+ include("{$template}/index_content_bottom"); ?> + +
+
+ +
+
include("{$layouts['path']}/bottom"); ?>
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/mylog/modify_form.php b/app/Views/admin/mylog/modify_form.php new file mode 100644 index 0000000..040274f --- /dev/null +++ b/app/Views/admin/mylog/modify_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/mylog/view.php b/app/Views/admin/mylog/view.php new file mode 100644 index 0000000..80061d8 --- /dev/null +++ b/app/Views/admin/mylog/view.php @@ -0,0 +1,17 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?>getFieldView($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?>
+
+
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/traffic/create_form.php b/app/Views/admin/traffic/create_form.php new file mode 100644 index 0000000..82d4599 --- /dev/null +++ b/app/Views/admin/traffic/create_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['formDatas'][$field] ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/traffic/download.php b/app/Views/admin/traffic/download.php new file mode 100644 index 0000000..c835c18 --- /dev/null +++ b/app/Views/admin/traffic/download.php @@ -0,0 +1,19 @@ + + + + $label): ?> + + + + + + + + + + + + + + +
getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?>
\ No newline at end of file diff --git a/app/Views/admin/traffic/index.php b/app/Views/admin/traffic/index.php new file mode 100644 index 0000000..80d0a62 --- /dev/null +++ b/app/Views/admin/traffic/index.php @@ -0,0 +1,59 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> + +section('content') ?> +
include("{$layouts['path']}/top"); ?>
+ + + + + +
include("{$layouts['path']}/left_menu"); ?> +
include("{$template}/index_header"); ?>
+
+ +
+ include("{$template}/index_content_filter"); ?> + 'batchjob_form', 'method' => "post"]) ?> + + + + + $label): ?> + + + + + + + + + getStatus() === DEFAULTS['STATUS']; + $rowClass = $isDefaultStatus ? "" : 'class="table-danger"'; + $num = $viewDatas['index_totalcount'] - (($viewDatas['page'] - 1) * $viewDatas['perpage'] + $cnt); + ?> + > + + $label): ?> + + + + + +
번호getListLabel($field, $label, $viewDatas) ?>작업
getListButton('modify', $num, $viewDatas) ?>getFieldView($field, $entity->$field, $viewDatas) ?> + getListButton('view', '', $viewDatas) ?>  + getListButton('delete', '', $viewDatas) ?> +
+ include("{$template}/index_content_bottom"); ?> + +
+
+ +
+
include("{$layouts['path']}/bottom"); ?>
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/traffic/modify_form.php b/app/Views/admin/traffic/modify_form.php new file mode 100644 index 0000000..040274f --- /dev/null +++ b/app/Views/admin/traffic/modify_form.php @@ -0,0 +1,22 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?> +
+
+
"btn btn-outline btn-primary")); ?>
+ +
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/traffic/view.php b/app/Views/admin/traffic/view.php new file mode 100644 index 0000000..80061d8 --- /dev/null +++ b/app/Views/admin/traffic/view.php @@ -0,0 +1,17 @@ +extend(LAYOUTS[$viewDatas['layout']]['path']) ?> +alertTrait(session('message')) : "" ?> +section('content') ?> +
+
include("templates/{$viewDatas['layout']}/form_content_top"); ?>
+ + $label): ?> + + + + + +
getFieldLabel($field, $label, $viewDatas) ?>getFieldView($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?>
+
+
include("templates/{$viewDatas['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/layouts/admin/left_menu/base.php b/app/Views/layouts/admin/left_menu/base.php index 999d8f7..9f05b48 100644 --- a/app/Views/layouts/admin/left_menu/base.php +++ b/app/Views/layouts/admin/left_menu/base.php @@ -3,4 +3,10 @@
트래픽 관리 +
+
+ 수집 관리 +
+
+ 로그 관리
\ No newline at end of file