dbmsv3 init...1

This commit is contained in:
choi.jh 2025-10-15 16:13:51 +09:00
parent 478210a903
commit 4f1114283b
29 changed files with 455 additions and 135 deletions

View File

@ -417,8 +417,8 @@ define("SERVICE", [
define("SERVERPART", [
"CNT_RANGE" => array_combine(range(1, 10), range(1, 10)),
"SERVER_PARTTYPES" => ['CPU', 'RAM', 'DISK'],
"SERVICE_PARTTYPES" => ['SWITCH', 'OS', 'SOFTWARE', 'CS', 'IP'],
"ALL_PARTTYPES" => ['CPU', 'RAM', 'DISK', 'OS', 'SOFTWARE', 'SWITCH', 'IP', 'CS'],
"SERVICE_PARTTYPES" => ['OS', 'SOFTWARE', 'CS', 'IP'],
"ALL_PARTTYPES" => ['CPU', 'RAM', 'DISK', 'OS', 'SOFTWARE', 'IP', 'CS'],
"CPU" => [
"ATYPE" => [["UID" => 1, "CNT" => 1, "EXTRA" => ""]],
"BTYPE" => [["UID" => 2, "CNT" => 1, "EXTRA" => ""]],

View File

@ -51,25 +51,31 @@ class ServerController extends EquipmentController
}
return $result;
}
private function pre_form_process(): void
{
//공통 처리
$ips = [];
foreach ($this->getService()->getIPService()->getEntities(['status' => STATUS['AVAILABLE']]) as $ipEntity) {
$ips[] = $ipEntity->getTitle();
}
$this->ips = $ips;
$switchs = [];
foreach ($this->getService()->getSwitchService()->getEntities(['status' => STATUS['AVAILABLE']]) as $switchEntity) {
$switchs[] = $switchEntity->getTitle();
}
$this->switchs = $switchs;
}
protected function create_form_process(): void
{
$formDatas = $this->getService()->getFormDatas();
$formDatas['code'] = sprintf("%d%dXX-M%d", date("y"), ceil((int)date("m") / 3), $this->getService()->getLatestPK());
$this->getService()->setFormDatas($formDatas);
$ips = [];
foreach ($this->getService()->getIPService()->getEntities(['status' => STATUS['AVAILABLE']]) as $ipEntity) {
$ips[] = $ipEntity->getTitle();
}
$this->ips = $ips;
$this->pre_form_process();
parent::create_form_process();
}
protected function modify_form_process(mixed $entity): ServerEntity
{
$ips = [];
foreach ($this->getService()->getIPService()->getEntities(['status' => STATUS['AVAILABLE']]) as $ipEntity) {
$ips[] = $ipEntity->getTitle();
}
$this->ips = $ips;
$this->pre_form_process();
return parent::modify_form_process($entity);
}
}

View File

@ -4,8 +4,8 @@
"settings": {
"width": 3000,
"height": 3000,
"scrollTop": -1484.7873,
"scrollLeft": -632,
"scrollTop": -638.7873,
"scrollLeft": -730,
"zoomLevel": 0.79,
"show": 511,
"database": 4,
@ -207,6 +207,7 @@
"foBGnViYEjNlWIAhXeuLw",
"4O_bDo914qohikJ_37Ung",
"OwsCuEWoHNZ8zov4IClUR",
"zJMN95OIXgOJBt4puEvQK",
"-egu-8EQDsUJcOi-nzl74",
"lwUlKlMynruDkBuFpj-eN",
"ut3UlHsNjxqNgAzENBkfy",
@ -226,6 +227,7 @@
"hQM1tPHn6MrCa4pIL7t7w",
"4O_bDo914qohikJ_37Ung",
"OwsCuEWoHNZ8zov4IClUR",
"zJMN95OIXgOJBt4puEvQK",
"-egu-8EQDsUJcOi-nzl74",
"Mr4qiMpKO4UVj3aZ3HueW",
"lwUlKlMynruDkBuFpj-eN",
@ -241,7 +243,7 @@
"color": ""
},
"meta": {
"updateAt": 1755654895097,
"updateAt": 1760509572092,
"createAt": 1745819764137
}
},
@ -256,6 +258,7 @@
"34psXzS7RLX0sWXZyDGGf",
"I8DumSwkLWz-Ve5_vc0uE",
"4t01_53QawHcw0lfY4zDm",
"jnDePNx6_yIPBt4qYZguP",
"9F6QpQqxeEggZ0FHM81O1",
"tsDqk1dzwzUtvBzpjmarJ",
"hmZlcR-Pw2C_ife1zzo5o",
@ -291,6 +294,7 @@
"I8DumSwkLWz-Ve5_vc0uE",
"m77kSp3scTgMhInPBjsc3",
"4t01_53QawHcw0lfY4zDm",
"jnDePNx6_yIPBt4qYZguP",
"9F6QpQqxeEggZ0FHM81O1",
"EKrwHre6e66jqAMnAW_KR",
"Z2CriPHsk4OV0AD1jAhM4",
@ -338,7 +342,7 @@
"color": ""
},
"meta": {
"updateAt": 1759457394197,
"updateAt": 1760509478899,
"createAt": 1745819764137
}
},
@ -521,6 +525,7 @@
"7V8vH8k_wZV5zwh_OLNFs",
"ALRvTZjYrv4K1ltFn30Mn",
"TFkQ1ID6ShcMqf9wLGEP1",
"csqnGDkLoJuqw_OWzQvVn",
"DSAUgD7rG7Lzm2-jVWKA3",
"CsIzpJzZlzCRy82KiTfhJ",
"6WOE-jsg5rFe2X04atr-Y",
@ -545,6 +550,7 @@
"RJRgO2-42FxCW0ucjngu9",
"iMCMcnQGafCPo46R91hOK",
"TFkQ1ID6ShcMqf9wLGEP1",
"csqnGDkLoJuqw_OWzQvVn",
"DSAUgD7rG7Lzm2-jVWKA3",
"CsIzpJzZlzCRy82KiTfhJ",
"6WOE-jsg5rFe2X04atr-Y",
@ -559,7 +565,7 @@
"color": ""
},
"meta": {
"updateAt": 1755654890491,
"updateAt": 1760509577174,
"createAt": 1745819764140
}
},
@ -941,6 +947,7 @@
"wYamirJUg21s94uxd_YhW",
"gbR9hOeDvjnrJAxI4vLf9",
"PV9lD8qRmTrg8bMT4t3WG",
"1r8TTwszjYLo1rucQ7S1q",
"VP7GvkqWejNbQZc-tmlr_",
"UzQFCo9RFEeqMUnp4xCp_",
"rXvRKMW6wEsJR5E6IwWZI",
@ -953,6 +960,7 @@
"QD0EVLU6BeTsEsNO3MAgd",
"gbR9hOeDvjnrJAxI4vLf9",
"PV9lD8qRmTrg8bMT4t3WG",
"1r8TTwszjYLo1rucQ7S1q",
"VP7GvkqWejNbQZc-tmlr_",
"UzQFCo9RFEeqMUnp4xCp_",
"rXvRKMW6wEsJR5E6IwWZI",
@ -967,7 +975,7 @@
"color": ""
},
"meta": {
"updateAt": 1755654886662,
"updateAt": 1760509586845,
"createAt": 1755488593741
}
},
@ -9542,9 +9550,89 @@
"widthDefault": 60
},
"meta": {
"updateAt": 1759457823730,
"updateAt": 1760509460680,
"createAt": 1759457280264
}
},
"jnDePNx6_yIPBt4qYZguP": {
"id": "jnDePNx6_yIPBt4qYZguP",
"tableId": "B4qGh3KZsXHQ3_4EOgwJZ",
"name": "switch",
"comment": "",
"dataType": "VARCHAR(10)",
"default": "",
"options": 4,
"ui": {
"keys": 0,
"widthName": 60,
"widthComment": 60,
"widthDataType": 75,
"widthDefault": 60
},
"meta": {
"updateAt": 1760509480724,
"createAt": 1760509465626
}
},
"zJMN95OIXgOJBt4puEvQK": {
"id": "zJMN95OIXgOJBt4puEvQK",
"tableId": "GDEF0_WuOpaYtsZxjn2zM",
"name": "content",
"comment": "내용",
"dataType": "TEXT",
"default": "",
"options": 0,
"ui": {
"keys": 0,
"widthName": 60,
"widthComment": 60,
"widthDataType": 60,
"widthDefault": 60
},
"meta": {
"updateAt": 1760509569951,
"createAt": 1760509569950
}
},
"csqnGDkLoJuqw_OWzQvVn": {
"id": "csqnGDkLoJuqw_OWzQvVn",
"tableId": "jO40Ej5EXImXnadoJo9bn",
"name": "content",
"comment": "내용",
"dataType": "TEXT",
"default": "",
"options": 0,
"ui": {
"keys": 0,
"widthName": 60,
"widthComment": 60,
"widthDataType": 60,
"widthDefault": 60
},
"meta": {
"updateAt": 1760509575028,
"createAt": 1760509575028
}
},
"1r8TTwszjYLo1rucQ7S1q": {
"id": "1r8TTwszjYLo1rucQ7S1q",
"tableId": "PdXX5ghGi8ZK89G9OjtnQ",
"name": "content",
"comment": "내용",
"dataType": "TEXT",
"default": "",
"options": 0,
"ui": {
"keys": 0,
"widthName": 60,
"widthComment": 60,
"widthDataType": 60,
"widthDefault": 60
},
"meta": {
"updateAt": 1760509585504,
"createAt": 1760509585503
}
}
},
"relationshipEntities": {
@ -9708,7 +9796,7 @@
"10Ii30CtjhJA-dPVnX2Z-"
],
"x": 565.0848,
"y": 153.6977,
"y": 159.6977,
"direction": 2
},
"meta": {
@ -9736,7 +9824,7 @@
"J1dtvqmAyJxT6QtuZq7IA"
],
"x": 566.1238,
"y": 503.372,
"y": 509.372,
"direction": 2
},
"meta": {
@ -9764,7 +9852,7 @@
"z86v6qGtWsrVhzZfUo_7d"
],
"x": 562.4083,
"y": 802.179,
"y": 808.179,
"direction": 2
},
"meta": {
@ -9792,7 +9880,7 @@
"wYamirJUg21s94uxd_YhW"
],
"x": 562.4083,
"y": 938.179,
"y": 956.179,
"direction": 2
},
"meta": {
@ -9820,7 +9908,7 @@
"7V8vH8k_wZV5zwh_OLNFs"
],
"x": 566.1238,
"y": 639.3720000000001,
"y": 657.3720000000001,
"direction": 2
},
"meta": {
@ -9848,7 +9936,7 @@
"UdKStw4LaMSQ0QxI2PfV_"
],
"x": 565.0848,
"y": 325.6977,
"y": 343.6977,
"direction": 2
},
"meta": {
@ -9979,7 +10067,7 @@
"RITMHZcQAJ7KvtxkTtMv-"
],
"x": 1746.7498,
"y": 2077.4788,
"y": 2092.4788,
"direction": 2
},
"end": {
@ -10016,7 +10104,7 @@
"4iRyOhmW3b7kbiZT8lQyY"
],
"x": 1746.7498,
"y": 1881.4788,
"y": 1884.4788,
"direction": 2
},
"meta": {
@ -10091,7 +10179,7 @@
"RITMHZcQAJ7KvtxkTtMv-"
],
"x": 1086.7498,
"y": 2028.4788,
"y": 2040.4788,
"direction": 1
},
"end": {
@ -10119,7 +10207,7 @@
"RITMHZcQAJ7KvtxkTtMv-"
],
"x": 1746.7498,
"y": 2175.4788,
"y": 2196.4788,
"direction": 2
},
"end": {
@ -10427,7 +10515,7 @@
"RITMHZcQAJ7KvtxkTtMv-"
],
"x": 1746.7498,
"y": 1979.4788,
"y": 1988.4788,
"direction": 2
},
"end": {

File diff suppressed because one or more lines are too long

View File

@ -9,17 +9,17 @@ class AccountEntity extends CustomerEntity
const PK = AccountModel::PK;
const TITLE = AccountModel::TITLE;
const DEFAULT_STATUS = STATUS['DEPOSIT'];
final public function getUserUID(): int
final public function getUserUID(): int|null
{
return $this->attributes['user_uid'];
return $this->attributes['user_uid'] ?? null;
}
final public function getClientInfoUID(): int
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
//기본기능
public function getContent(): string|null
{
return $this->attributes['content'];
return $this->attributes['content'] ?? null;
}
}

View File

@ -11,7 +11,7 @@ class ClientEntity extends CustomerEntity
const DEFAULT_STATUS = STATUS['AVAILABLE'];
final public function getUserUID(): int|null
{
return $this->attributes['user_uid'];
return $this->attributes['user_uid'] ?? null;
}
//기본기능
public function getCustomTitle(string $field = ClientModel::TITLE): string

View File

@ -11,15 +11,15 @@ class CouponEntity extends CustomerEntity
const DEFAULT_STATUS = STATUS['DEPOSIT'];
final public function getUserUID(): int|null
{
return $this->attributes['user_uid'];
return $this->attributes['user_uid'] ?? null;
}
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
//기본기능
public function getContent(): string|null
{
return $this->attributes['content'];
return $this->attributes['content'] ?? null;
}
}

View File

@ -15,11 +15,11 @@ class PointEntity extends CustomerEntity
}
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
//기본기능
public function getContent(): string|null
{
return $this->attributes['content'];
return $this->attributes['content'] ?? null;
}
}

View File

@ -18,7 +18,7 @@ class ServiceEntity extends CustomerEntity
}
final public function getServerEntity(): ServerEntity|null
{
return $this->attributes['serverEntity'];
return $this->attributes['serverEntity'] ?? null;
}
final public function setPaymentEntity(PaymentEntity $entity): self
{
@ -27,23 +27,23 @@ class ServiceEntity extends CustomerEntity
}
final public function getPaymentEntity(): PaymentEntity|null
{
return $this->attributes['paymentEntity'];
return $this->attributes['paymentEntity'] ?? null;
}
final public function getUserUID(): int|null
{
return $this->attributes['user_uid'];
return $this->attributes['user_uid'] ?? null;
}
final public function getClientInfoUID(): int
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
final public function getServerInfoUID(): int
final public function getServerInfoUID(): int|null
{
return $this->attributes['serverinfo_uid'];
return $this->attributes['serverinfo_uid'] ?? null;
}
final public function getPaymentUID(): string|null
{
return $this->attributes['payment_uid'];
return $this->attributes['payment_uid'] ?? null;
}
//기본기능용
public function getCustomTitle(string $field = ServiceModel::TITLE): string
@ -91,6 +91,6 @@ class ServiceEntity extends CustomerEntity
}
public function getHistory(): string|null
{
return $this->attributes['history'];
return $this->attributes['history'] ?? null;
}
}

View File

@ -11,11 +11,11 @@ class ServerEntity extends EquipmentEntity
const DEFAULT_STATUS = STATUS['AVAILABLE'];
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
final public function getServiceInfoUID(): int|null
{
return $this->attributes['serviceinfo_uid'];
return $this->attributes['serviceinfo_uid'] ?? null;
}
//기본기능용
public function getCustomTitle(string $field = ServerModel::TITLE): string
@ -24,15 +24,19 @@ class ServerEntity extends EquipmentEntity
}
final public function getCode(): string
{
return $this->attributes['code'] ?? "";
return $this->attributes['code'];
}
public function getPrice(): int
{
return $this->attributes['price'] ?? 0;
return $this->attributes['price'];
}
public function getType(): string
{
return $this->attributes['type'] ?? "";
return $this->attributes['type'];
}
public function getSwitch(): string|null
{
return $this->attributes['switch'] ?? null;
}
public function getIP(): string|null
{

View File

@ -26,24 +26,23 @@ class ServerPartEntity extends EquipmentEntity
}
final public function getPaymentEntity(): PaymentEntity|null
{
return $this->attributes['paymentEntity'];
return $this->attributes['paymentEntity'] ?? null;
}
final public function getServerInfoUID(): int
final public function getServerInfoUID(): int|null
{
return $this->attributes['serverinfo_uid'];
return $this->attributes['serverinfo_uid'] ?? null;
}
public function getPartUID(): int
public function getPartUID(): int|null
{
return intval($this->attributes['part_uid']);
return $this->attributes['part_uid'] ?? null;
}
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
final public function getServiceInfoUID(): int|null
{
return $this->attributes['serviceinfo_uid'];
return $this->attributes['serviceinfo_uid'] ?? null;
}
final public function getPaymentUID(): int|null
{

View File

@ -17,10 +17,10 @@ class CSEntity extends PartEntity
//기본기능
public function getAccountID(): string|null
{
return $this->attributes['accountid'];
return $this->attributes['accountid'] ?? null;
}
public function getDomain(): string|null
{
return $this->attributes['domain'];
return $this->attributes['domain'] ?? null;
}
}

View File

@ -9,13 +9,13 @@ class IPEntity extends PartEntity
const PK = IPModel::PK;
const TITLE = IPModel::TITLE;
const DEFAULT_STATUS = STATUS['AVAILABLE'];
final public function getLineInfoUID(): string
final public function getLineInfoUID(): int|null
{
return $this->attributes['lineinfo_uid'];
return $this->attributes['lineinfo_uid'] ?? null;
}
final public function getOldClientInfoUID(): string|null
final public function getOldClientInfoUID(): int|null
{
return $this->attributes['old_clientinfo_uid'];
return $this->attributes['old_clientinfo_uid'] ?? null;
}
//기본기능
public function getIP(): string

View File

@ -10,15 +10,15 @@ abstract class PartEntity extends CommonEntity
{
parent::__construct($data);
}
final public function getClientInfoUID(): string|null
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
}
final public function getServiceInfoUID(): string|null
final public function getServiceInfoUID(): int|null
{
return $this->attributes['serviceinfo_uid'];
}
final public function getServerInfoUID(): string|null
final public function getServerInfoUID(): int|null
{
return $this->attributes['serverinfo_uid'];
}

View File

@ -12,15 +12,15 @@ class PaymentEntity extends CommonEntity
const DEFAULT_STATUS = STATUS['UNPAID'];
final public function getUserUID(): int|null
{
return $this->attributes['user_uid'];
return $this->attributes['user_uid'] ?? null;
}
final public function getClientInfoUID(): int
final public function getClientInfoUID(): int|null
{
return $this->attributes['clientinfo_uid'];
return $this->attributes['clientinfo_uid'] ?? null;
}
final public function getServiceInfoUID(): int
final public function getServiceInfoUID(): int|null
{
return $this->attributes['serviceinfo_uid'];
return $this->attributes['serviceinfo_uid'] ?? null;
}
//기본기능
public function getBilling(): string
@ -41,7 +41,7 @@ class PaymentEntity extends CommonEntity
}
public function getContent(): string|null
{
return $this->attributes['content'];
return $this->attributes['content'] ?? null;
}
public function getCountDueAt(): string
{

View File

@ -31,7 +31,19 @@ class ServerHelper extends EquipmentHelper
"autocomplete" => "off",
...$extras
]);
$form .= "<div id=\"ipPanel\" class=\"ac-panel\" hidden></div></div>";
$form .= "<div id=\"ipPanel\" class=\"ac-panel\" hidden></div>";
$form .= "</div>";
break;
case 'switch': //값 그대료 표시
$form = "<div class=\"ac-wrap\" style=\"position:relative;\">";
$form .= form_input($field, $value ?? "", [
'id' => 'switchInput',
"placeholder" => "Switch 코드 입력",
"autocomplete" => "off",
...$extras
]);
$form .= "<div id=\"switchPanel\" class=\"ac-panel\" hidden></div>";
$form .= "</div>";
break;
case 'manufactur_at':
case 'format_at':

View File

@ -77,7 +77,13 @@ class ServerPartHelper extends EquipmentHelper
case 'SERVER':
$value = $viewDatas['serviceinfo_serverinfo_uid'] == $viewDatas['serverEntity']->getPK() ? "📌" : "<a href=\"/admin/customer/service/changeServer/{$viewDatas['serverEntity']->getServiceInfoUID()}?serverinfo_uid={$viewDatas['serverEntity']->getPK()}\">✔️</a>";
$value .= form_label(
sprintf("[%s] %s / %s", lang("Equipment/Server.TYPE")[$viewDatas['serverEntity']->getType()], $viewDatas['serverEntity']->getCode(), $viewDatas['serverEntity']->getIP()),
sprintf(
"[%s] %s / %s / %s",
lang("Equipment/Server.TYPE")[$viewDatas['serverEntity']->getType()],
$viewDatas['serverEntity']->getCode(),
$viewDatas['serverEntity']->getIP(),
$viewDatas['serverEntity']->getSwitch()
),
$field,
[
"data-src" => "/admin/equipment/server/modify/{$viewDatas['serverEntity']->getPK()}?ActionTemplate=server",

View File

@ -6,6 +6,7 @@ return [
'serviceinfo_uid' => "서비스번호",
'code' => "장비번호",
'type' => "형식",
'switch' => "스위치",
'ip' => "메인IP",
'title' => "모델명",
'price' => "기본가",

View File

@ -19,6 +19,7 @@ class ServerModel extends EquipmentModel
"serviceinfo_uid",
"code",
"type",
"switch",
"ip",
"title",
"price",
@ -55,6 +56,10 @@ class ServerModel extends EquipmentModel
case "manufactur_at":
$rule = "required|valid_date";
break;
case "switch":
$rule = "permit_empty|trim|string";
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[{$this->table}.{$field}]" : "";
break;
case "ip":
$rule = "permit_empty|trim|valid_ip[both]"; //ipv4 , ipv6 , both(ipv4,ipv6)
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[{$this->table}.{$field}]" : "";

View File

@ -11,12 +11,14 @@ use App\Services\Customer\ServiceService;
use App\Services\Equipment\EquipmentService;
use App\Services\Equipment\ServerPartService;
use App\Services\Part\IPService;
use App\Services\Part\SWITCHService;
class ServerService extends EquipmentService implements ServiceInterface
{
private ?ServiceService $_serviceService = null;
private ?ServerPartService $_serverPartService = null;
private ?IPService $_ipService = null;
private ?SWITCHService $_switchService = null;
public function __construct()
{
parent::__construct(new ServerModel(), new ServerHelper());
@ -27,6 +29,7 @@ class ServerService extends EquipmentService implements ServiceInterface
return [
"code",
"type",
"switch",
"ip",
"title",
"price",
@ -47,6 +50,7 @@ class ServerService extends EquipmentService implements ServiceInterface
'clientinfo_uid',
'serviceinfo_uid',
"type",
"switch",
"ip",
'title',
'price',
@ -83,6 +87,13 @@ class ServerService extends EquipmentService implements ServiceInterface
}
return $this->_ipService;
}
final public function getSwitchService(): SWITCHService
{
if (!$this->_switchService) {
$this->_switchService = new SWITCHService();
}
return $this->_switchService;
}
final public function getServerPartService(): ServerPartService
{
if (!$this->_serverPartService) {
@ -209,6 +220,10 @@ class ServerService extends EquipmentService implements ServiceInterface
$entity = parent::create($formDatas);
//서버의 Type별 서버파트정보등록(서버파트연결 자동등록용)
$entity = $this->getServerPartService()->setServer('create', $entity, []);
if ($entity->getSwitch() !== null) { //Switch가 정의되어 있으면
$entity = $this->getSwitchService()->setServer('create', $entity, []);
}
// dd($entity);
if ($entity->getIP() !== null) { //IP가 정의되어 있으면
$entity = $this->getIPService()->setServer('create', $entity, []);
}
@ -229,6 +244,13 @@ class ServerService extends EquipmentService implements ServiceInterface
if ($entity->getServiceInfoUID() !== null && $entity->getType() !== "alternative") {
$this->getServiceService()->setAmount($this->getServiceService()->getEntity($entity->getServiceInfoUID()));
}
//Switch정보 수정
if ($oldEntity->getSwitch() !== null) { //기존 서버정보에 Switch가 정의되어 있으면
$oldEntity = $this->getSwitchService()->setServer('delete', $oldEntity, []);
}
if ($entity->getSwitch() !== null) { //Switch가 정의되어 있으면
$entity = $this->getSwitchService()->setServer('create', $entity, []);
}
//IP정보 수정
if ($oldEntity->getIP() !== null) { //기존 서버정보에 IP가 정의되어 있으면
$oldEntity = $this->getIPService()->setServer('delete', $oldEntity, []);

View File

@ -120,7 +120,7 @@ class IPService extends PartService implements ServerInterface
$this->getModel()->orderBy('INET_ATON(ip)', 'ASC');
parent::setOrderBy($field, $value);
}
//서버파트관련 작업
//서버관련 작업
public function setServer(string $action, ServerEntity $serverEntity, array $serverDatas): ServerEntity
{
switch ($action) {
@ -137,7 +137,7 @@ class IPService extends PartService implements ServerInterface
$entity = $this->getEntity(['ip' => $serverEntity->getIP()]);
if ($entity instanceof IPEntity) {
if ($entity->getStatus() !== STATUS['AVAILABLE']) {
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: {$entity->getIP()}는 사용중인 IP입니다.");
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: {$serverEntity->getIP()}는 사용중인 IP입니다.");
}
$entity = parent::modify($entity, $formDatas);
}

View File

@ -2,15 +2,17 @@
namespace App\Services\Part;
use App\Entities\Equipment\ServerEntity;
use App\Entities\Equipment\ServerPartEntity;
use App\Entities\Part\SWITCHEntity;
use App\Helpers\Part\SWITCHHelper;
use App\Interfaces\Equipment\ServerInterface;
use App\Models\Part\SWITCHModel;
use App\Services\Customer\ServiceService;
use App\Services\Equipment\ServerService;
use App\Services\Part\PartService;
class SWITCHService extends PartService
class SWITCHService extends PartService implements ServerInterface
{
private ?ServiceService $_serviceService = null;
private ?ServerService $_serverService = null;
@ -88,7 +90,50 @@ class SWITCHService extends PartService
$this->getModel()->orderBy('code', 'ASC');
parent::setOrderBy($field, $value);
}
//서버관련 작업
public function setServer(string $action, ServerEntity $serverEntity, array $serverDatas): ServerEntity
{
switch ($action) {
case 'create':
$formDatas = [];
$formDatas['clientinfo_uid'] = $serverEntity->getClientInfoUID();
$formDatas['serviceinfo_uid'] = $serverEntity->getServiceInfoUID();
$formDatas['serverinfo_uid'] = $serverEntity->getPK();
$formDatas['status'] = STATUS['OCCUPIED'];
if (!array_key_exists('status', $formDatas)) {
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: Switch상태가 설정되지 않았습니다.");
}
//Switch정보에서 해당하는 Switch가 있으면 가져와서 사용중인지 체크 후 수정
$entity = $this->getEntity(['code' => $serverEntity->getSwitch()]);
if ($entity instanceof SWITCHEntity) {
if ($entity->getStatus() !== STATUS['AVAILABLE']) {
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: {$serverEntity->getSwitch()}는 사용중인 Switch입니다.");
}
$entity = parent::modify($entity, $formDatas);
}
break;
case 'delete': //반드시 serverPartEntity 사용해야함
$formDatas = [];
$formDatas['clientinfo_uid'] = null;
$formDatas['serviceinfo_uid'] = null;
$formDatas['serverinfo_uid'] = null;
$formDatas['old_clientinfo_uid'] = $serverEntity->getClientInfoUID() ?? null;
$formDatas['status'] = STATUS['AVAILABLE'];
if (!array_key_exists('status', $formDatas)) {
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: Switch상태가 설정되지 않았습니다.");
}
//Switch정보가져와서 있으면 수정
$entity = $this->getEntity(['code' => $serverEntity->getSwitch()]);
if ($entity instanceof SWITCHEntity) {
$entity = parent::modify($entity, $formDatas);
}
break;
default:
throw new \Exception(__METHOD__ . ":{$action}에서 오류발생: 정의되지 않은 작업입니다.");
// break;
}
return $serverEntity;
}
//서버파트관련 작업
public function setServerPart(string $action, ServerPartEntity $serverPartEntity, array $serverPartDatas): ServerPartEntity
{

View File

@ -36,10 +36,14 @@
background: #f1f5f9;
}
</style>
<script src="/js/admin/server/form.js"></script>
<script script script id="ipData" type="application/json">
<?= json_encode($viewDatas['ips'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
<script id="ipData" type="application/json">
<?= json_encode($viewDatas['ips'] ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
</script>
<script id="switchData" type="application/json">
<?= json_encode($viewDatas['switchs'] ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
</script>
<script src="/js/admin/server/ipAutoComplete.js"></script>
<script src="/js/admin/server/switchAutoComplete.js"></script>
<div id=" container" class="content">
<div class="form_top"><?= $this->include("templates/{$viewDatas['layout']}/form_content_top"); ?></div>
<?= form_open(current_url(), $viewDatas['forms']['attributes'], $viewDatas['forms']['hiddens']) ?>

View File

@ -36,12 +36,14 @@
<th class="index_head_short_column">번호</th>
<th class="index_head_short_column">
<?= $viewDatas['service']->getHelper()->getListLabel('clientinfo_uid', lang("{$viewDatas['class_path']}.label.clientinfo_uid"), $viewDatas) ?>/
<?= $viewDatas['service']->getHelper()->getListLabel('serviceinfo_uid', lang("{$viewDatas['class_path']}.label.serviceinfo_uid"), $viewDatas) ?>
</th>
<th class="index_head_short_column">
<?= $viewDatas['service']->getHelper()->getListLabel('type', lang("{$viewDatas['class_path']}.label.type"), $viewDatas) ?>/
<?= $viewDatas['service']->getHelper()->getListLabel('title', lang("{$viewDatas['class_path']}.label.title"), $viewDatas) ?>
</th>
<th class="index_head_short_column">
<?= $viewDatas['service']->getHelper()->getListLabel('switch', lang("{$viewDatas['class_path']}.label.switch"), $viewDatas) ?>
</th>
<th class="index_head_short_column">
<?= $viewDatas['service']->getHelper()->getListLabel('ip', lang("{$viewDatas['class_path']}.label.ip"), $viewDatas) ?>
</th>
@ -71,12 +73,14 @@
<td nowrap><?= $viewDatas['service']->getHelper()->getListButton('modify', "", $viewDatas) ?></td>
<td nowrap>
<?= $viewDatas['service']->getHelper()->getFieldView('clientinfo_uid', $entity->getClientInfoUID(), $viewDatas) ?><BR>
<?= $viewDatas['service']->getHelper()->getFieldView('serviceinfo_uid', $entity->getServiceInfoUID(), $viewDatas) ?>
</td>
<td nowrap>
<?= $viewDatas['service']->getHelper()->getFieldView('type', $entity->type, $viewDatas) ?><BR>
<?= $viewDatas['service']->getHelper()->getFieldView('title', $entity->getTitle(), $viewDatas) ?>
</td>
<td nowrap>
<?= $viewDatas['service']->getHelper()->getFieldView('switch', $entity->switch, $viewDatas) ?>
</td>
<td nowrap>
<?= $viewDatas['service']->getHelper()->getFieldView('ip', $entity->ip, $viewDatas) ?>
</td>

View File

@ -36,10 +36,14 @@
background: #f1f5f9;
}
</style>
<script src="/js/admin/server/form.js"></script>
<script script script id="ipData" type="application/json">
<?= json_encode($viewDatas['ips'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
<script id="ipData" type="application/json">
<?= json_encode($viewDatas['ips'] ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
</script>
<script id="switchData" type="application/json">
<?= json_encode($viewDatas['switchs'] ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>
</script>
<script src="/js/admin/server/ipAutoComplete.js"></script>
<script src="/js/admin/server/switchAutoComplete.js"></script>
<div id="container" class="content">
<div class="form_top"><?= $this->include("templates/{$viewDatas['layout']}/form_content_top"); ?></div>
<table class="table table-bordered">

View File

@ -1,15 +0,0 @@
<table class="table table-bordered table-hover table-striped">
<tr>
<th>항목</th>
<th>갯수</th>
<th>포맷</th>
</tr>
<?php foreach ($partCellDatas['entities'] as $entity): ?>
<?php $partCellDatas['entity'] = $entity; ?>
<tr>
<?php foreach (['title', 'stock', 'format'] as $field): ?>
<td nowrap><?= $partCellDatas['service']->getHelper()->getFieldView($field, $entity->$field, $partCellDatas) ?></td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</table>

View File

@ -1,14 +0,0 @@
<table class="table table-bordered table-hover table-striped">
<tr>
<th>항목</th>
<th>갯수</th>
</tr>
<?php foreach ($partCellDatas['entities'] as $entity): ?>
<?php $partCellDatas['entity'] = $entity; ?>
<tr>
<?php foreach (['title', 'stock'] as $field): ?>
<td nowrap><?= $partCellDatas['service']->getHelper()->getFieldView($field, $entity->$field, $partCellDatas) ?></td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</table>

View File

@ -162,7 +162,6 @@ function parseEmbeddedJson(id){
document.addEventListener('DOMContentLoaded', () => {
// ipData <script>에 서버가 넣어준 배열 사용 (API 호출 없음)
const ips = parseEmbeddedJson('ipData');
const ac = new IpAutoComplete('#ipInput', '#ipPanel', ips, {
validateIPv4: true,
enforceListOnly: false,

View File

@ -0,0 +1,147 @@
class SwitchAutoComplete {
/**
* @param {HTMLElement|string} input
* @param {HTMLElement|string} panel
* @param {string[]} switchArray
* @param {object} opts
*/
constructor(input, panel, switchArray = [], opts = {}) {
this.inputEl = typeof input === 'string' ? document.querySelector(input) : input;
this.panelEl = typeof panel === 'string' ? document.querySelector(panel) : panel;
if (!this.inputEl || !this.panelEl) throw new Error('Invalid input/panel element');
this.opts = Object.assign({
previewOnFocus: true,
previewCount: 30,
resultLimit: 1000
}, opts);
this.setArray(switchArray);
this.activeIndex = -1;
// 이벤트 바인딩
this.onInput = this._handleInput.bind(this);
this.onFocus = this._handleFocus.bind(this);
this.onKeydown = this._handleKeydown.bind(this);
this.onClickOutside = this._handleClickOutside.bind(this);
this.inputEl.addEventListener('input', this.onInput);
this.inputEl.addEventListener('focus', this.onFocus);
this.inputEl.addEventListener('keydown', this.onKeydown);
document.addEventListener('mousedown', this.onClickOutside);
}
destroy() {
this.inputEl.removeEventListener('input', this.onInput);
this.inputEl.removeEventListener('focus', this.onFocus);
this.inputEl.removeEventListener('keydown', this.onKeydown);
document.removeEventListener('mousedown', this.onClickOutside);
this.hidePanel();
}
setArray(arr) {
this.switchArray = Array.from(new Set((arr || []).filter(Boolean)));
}
_handleInput(e) {
const q = (e.target.value || '').trim();
this._filterAndRender(q);
}
_handleFocus() {
if (!this.inputEl.value && this.opts.previewOnFocus) {
this._renderPanel(this.switchArray.slice(0, this.opts.resultLimit));
this.showPanel();
}
}
_handleKeydown(e) {
if (this.panelEl.hidden) return;
const items = this._items();
if (!items.length) return;
if (e.key === 'ArrowDown') { e.preventDefault(); this._move(1); }
else if (e.key === 'ArrowUp') { e.preventDefault(); this._move(-1); }
else if (e.key === 'Enter') {
if (this.activeIndex >= 0) { e.preventDefault(); this._pick(items[this.activeIndex].dataset.value); }
} else if (e.key === 'Escape') { this.hidePanel(); }
}
_handleClickOutside(e) {
if (!this.inputEl.closest('.ac-wrap')?.contains(e.target)) this.hidePanel();
}
_filterAndRender(query) {
if (!query) {
this.hidePanel();
return;
}
const q = query.toLowerCase();
let results = this.switchArray.filter(s => s.toLowerCase().includes(q));
if (this.opts.resultLimit > 0) results = results.slice(0, this.opts.resultLimit);
if (results.length) { this._renderPanel(results); this.showPanel(); }
else { this.hidePanel(); }
}
_renderPanel(list) {
this.panelEl.innerHTML = '';
this.activeIndex = -1;
const frag = document.createDocumentFragment();
list.forEach((sw) => {
const item = document.createElement('div');
item.className = 'ac-item';
item.textContent = sw;
item.dataset.value = sw;
item.addEventListener('mousedown', (ev) => { ev.preventDefault(); this._pick(sw); });
frag.appendChild(item);
});
this.panelEl.appendChild(frag);
}
_items() { return Array.from(this.panelEl.querySelectorAll('.ac-item')); }
_move(delta) {
const items = this._items();
if (!items.length) return;
this.activeIndex = (this.activeIndex + delta + items.length) % items.length;
items.forEach(el => el.classList.remove('active'));
const el = items[this.activeIndex];
el.classList.add('active');
el.scrollIntoView({ block: 'nearest' });
}
_pick(value) {
this.inputEl.value = value;
this.hidePanel();
}
showPanel() { this.panelEl.hidden = false; }
hidePanel() { this.panelEl.hidden = true; this.activeIndex = -1; }
}
/* switchData(JSON) 읽기 */
function parseEmbeddedJson(id) {
const el = document.getElementById(id);
if (!el) return [];
let txt = el.textContent || '';
txt = txt
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/(^|[^:])\/\/.*$/mg, '$1')
.replace(/,\s*([}\]])/g, '$1');
try {
const data = JSON.parse(txt);
return Array.isArray(data) ? data : [];
} catch (e) {
console.error('switchData parse error', e);
return [];
}
}
/* 초기화 */
document.addEventListener('DOMContentLoaded', () => {
const switches = parseEmbeddedJson('switchData');
const ac = new SwitchAutoComplete('#switchInput', '#switchPanel', switches, {
previewOnFocus: true,
resultLimit: 2000
});
});