dbmsv4 init...1

This commit is contained in:
최준흠 2025-11-20 11:26:53 +09:00
parent 989a8a33ab
commit 365d0a9af9
16 changed files with 170 additions and 93 deletions

View File

@ -112,6 +112,7 @@ abstract class AbstractWebController extends Controller
*/
protected function action_render_process(string $view_file, array $viewDatas, ?string $template_path = null): string
{
// dd($viewDatas);
$view_path = $viewDatas['layout'];
if ($template_path) {
$view_path .= DIRECTORY_SEPARATOR . $template_path;

View File

@ -20,6 +20,7 @@ abstract class AdminController extends CommonController
}
protected function action_init_process(string $action): void
{
parent::action_init_process($action);
$this->addViewDatas('layout', $this->getLayout());
$this->addViewDatas('helper', $this->service->getHelper());
$this->addViewDatas('formFields', $this->service->getFormService()->getFormFields());
@ -29,6 +30,5 @@ abstract class AdminController extends CommonController
$this->addViewDatas('index_actionButtons', $this->service->getFormService()->getactionButtons());
$this->addViewDatas('index_batchjobFields', $this->service->getFormService()->getBatchjobFilters());
$this->addViewDatas('index_batchjobButtons', $this->service->getFormService()->getBatchjobButtons());
parent::action_init_process($action);
}
}

View File

@ -3,13 +3,9 @@
namespace App\Controllers\Admin;
use App\Entities\PaymentEntity;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Validation\Exceptions\ValidationException;
use Psr\Log\LoggerInterface;
use RuntimeException;
class PaymentController extends AdminController
{
@ -25,19 +21,14 @@ class PaymentController extends AdminController
protected function action_init_process(string $action): void
{
$fields = [
"clientinfo_uid",
"serviceinfo_uid",
"serverpartinfo_uid",
"title",
"content",
"amount",
"billing",
"billing_at",
"pay",
"status",
"updated_at"
"content ",
];
$filters = ['role', 'status'];
$filters = ['clientinfo_uid', 'serviceinfo_uid', 'status', 'billing', 'pay'];
$batchjobFilters = ['status'];
// $actionButtons = ['view' => ICONS['SEARCH']];
// $batchjobButtons = [];
@ -47,14 +38,42 @@ class PaymentController extends AdminController
break;
case 'modify':
case 'modify_form':
$fields = ['title', 'amount', 'pay', 'status'];
$fields = ['title', 'amount', 'pay', 'status', 'content'];
break;
case 'view':
$fields = [...$fields, 'created_at'];
$fields = [
...$fields,
'clientinfo_uid',
"serviceinfo_uid",
'billing',
'title',
'amount',
'billing_at',
'pay',
'status',
'updated_at',
'countdown',
'user_uid',
'created_at',
'content'
];
break;
case 'index':
case 'download':
$fields = [...$fields, 'created_at'];
$fields = [
'clientinfo_uid',
"serviceinfo_uid",
'billing',
'title',
'amount',
'billing_at',
'pay',
'status',
'updated_at',
'countdown',
'user_uid',
'created_at'
];
break;
default:
throw new \Exception("[{$action}] 지원하지 않는 action입니다.");

View File

@ -235,7 +235,6 @@ abstract class CommonController extends AbstractCRUDController
$perpage = (int) $this->request->getVar('perpage') ?: intval(DEFAULTS['INDEX_PERPAGE'] ?? 10);
$this->addViewDatas('page', $page);
$this->addViewDatas('perpage', $perpage);
// 1. Total Count 계산을 위한 조건절 처리 (오버라이드 가능)
$this->index_condition_process($action);
$index_totalcount = $this->service->getTotalCount();
@ -244,7 +243,6 @@ abstract class CommonController extends AbstractCRUDController
// Pagination 설정
$this->addViewDatas('index_pagination', $this->pagenation_process($index_totalcount, $page, $perpage));
$this->addViewDatas('index_pagination_options', $this->pagenation_options_process($index_totalcount, $perpage));
// 2. 실제 리스트를 위한 조건절, LIMIT, OFFSET 처리 (오버라이드 가능)
$this->index_condition_process($action); // 조건절을 다시 호출하여 필터/검색어 유지
$this->service->setLimit($perpage);
@ -256,16 +254,11 @@ abstract class CommonController extends AbstractCRUDController
$this->addViewDatas('formDatas', $this->request->getVar() ?? []);
}
final public function index(): string|ResponseInterface
final public function index(): string
{
try {
$action = __FUNCTION__;
$this->action_init_process($action);
$this->index_process($action);
$this->index_result_process($action);
} catch (\Exception $e) {
session()->setFlashdata('message', $e->getMessage());
}
$action = __FUNCTION__;
$this->action_init_process($action);
$this->index_process($action);
return $this->index_result_process($action);
}

View File

@ -24,8 +24,21 @@ class ClientDTO extends CommonDTO
parent::__construct();
foreach ($datas as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
if ($key === 'role' && is_array($value)) {
// 배열일 경우, 쉼표로 구분된 문자열로 변환하여 저장
$this->role = implode(DEFAULTS["DELIMITER_ROLE"], $value);
} else {
$this->{$key} = $value;
}
}
}
}
public function __get(string $name)
{
// 'role' 속성을 요청했을 때만 특별히 처리
if ($name === 'role' && is_string($this->role)) {
return explode(DEFAULTS["DELIMITER_ROLE"], $this->role);
}
return parent::__get($name);
}
}

View File

@ -26,10 +26,6 @@ class ClientEntity extends CustomerEntity
{
return $this->attributes['site'];
}
public function getRole(): string
{
return $this->attributes['role'];
}
public function getAccountBalance(): int
{
return $this->attributes['account_balance'];
@ -46,4 +42,57 @@ class ClientEntity extends CustomerEntity
{
return $this->attributes['history'];
}
/*
* 사용자의 역할을 배열 형태로 반환합니다.
* DB의 JSON 또는 CSV 형식 데이터를 모두 배열로 복구할 있는 로직을 포함합니다.
* @return array
*/
public function getRole(): array
{
$role = $this->attributes['role'] ?? null;
// 1. 이미 배열인 경우 (방어적 코딩)
if (is_array($role)) {
return array_filter($role);
}
// 2. 문자열 데이터인 경우 처리
if (is_string($role) && !empty($role)) {
// 2-a. JSON 디코딩 시도 (기존 DB의 JSON 형식 처리)
$decodedRole = json_decode($role, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($decodedRole)) {
return $decodedRole;
}
// 2-b. JSON이 아니면 CSV로 가정하고 변환
$parts = explode(',', $role);
// 각 요소의 불필요한 공백과 따옴표 제거
$cleanedRoles = array_map(fn($item) => trim($item, " \t\n\r\0\x0B\""), $parts);
return array_filter($cleanedRoles);
}
// 3. 변환에 실패했거나 데이터가 없는 경우 빈 배열 반환
return [];
}
// --- Setter Methods ---
/**
* Role 데이터가 Entity에 설정될 호출되어, 입력된 CSV/JSON 문자열을 정리
* DB에 적합한 CSV 문자열로 최종 저장합니다.
* @param mixed $role 입력 데이터 (문자열 또는 배열)
*/
public function setRole(mixed $role)
{
$roleArray = [];
if (is_string($role)) {
// 1. 양쪽의 불필요한 따옴표와 공백을 제거하여 깨끗한 문자열 확보
$cleanRoleString = trim($role, " \t\n\r\0\x0B\"");
if (!empty($cleanRoleString)) {
$role = explode(DEFAULTS["DELIMITER_ROLE"], $cleanRoleString);
}
}
if (is_array($role)) {
//배열에도 불필요한 따옴표와 공백을 제거
$cleanedRoles = array_map(fn($item) => trim($item, " \t\n\r\0\x0B\""), $role);
$roleArray = array_filter($cleanedRoles);
}
// 💡 핵심: 최종적으로 DB에 삽입될 단일 CSV 문자열로 변환하여 저장합니다.
$this->attributes['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $roleArray);
}
}

View File

@ -44,8 +44,9 @@ class BoardForm extends CommonForm
}
return $rule;
}
public function getFormOption(string $field, array $options = []): array
public function getFormOption(string $field, array $options = ['options' => [], 'extras' => [], 'atttributes' => []]): array
{
$tempOptions = ['' => lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"];
switch ($field) {
case 'worker_uid':
foreach (service('userservice')->getEntities() as $entity) {

View File

@ -1,46 +0,0 @@
<?php
namespace App\Forms;
use App\Forms\CommonForm;
class CollectorForm extends CommonForm
{
public function __construct()
{
parent::__construct();
}
public function getFormRule(string $action, string $field): string
{
switch ($field) {
case "trafficinfo_uid":
case "in":
case "out":
case "raw_in":
case "raw_out":
$rule = "required|numeric";
break;
default:
$rule = parent::getFormRule($action, $field);
break;
}
return $rule;
}
public function getFormOption(string $field, array $options = ['options' => [], 'extras' => [], 'atttributes' => []]): array
{
$tempOptions = ['' => lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"];
switch ($field) {
case 'trafficinfo_uid':
foreach (service('trafficservice')->getEntities() as $entity) {
$tempOptions[$entity->getPK()] = $entity->getCustomTitle();
}
$options['options'] = $tempOptions;
break;
default:
$options = parent::getFormOption($field, $options);
break;
}
return $options;
}
}

View File

@ -194,7 +194,11 @@ abstract class CommonForm
$options['options'] = $tempOptions;
break;
default:
foreach (lang($this->getAttribute('class_path') . "." . strtoupper($field)) as $key => $label) {
$optionDatas = lang($this->getAttribute('class_path') . "." . strtoupper($field));
if (!is_array($optionDatas)) {
throw new \Exception(__METHOD__ . "에서 오류발생:{$field}가 배열값이 아닙니다.");
}
foreach ($optionDatas as $key => $label) {
$tempOptions[$key] = $label;
}
$options['options'] = $tempOptions;

View File

@ -40,4 +40,22 @@ class PaymentForm extends CommonForm
}
return $rule;
}
public function getFormOption(string $field, array $options = ['options' => [], 'extras' => [], 'atttributes' => []]): array
{
$tempOptions = ['' => lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택"];
switch ($field) {
case 'serviceinfo_uid':
foreach (service('customer_serviceservice')->getEntities() as $entity) {
$tempOptions[$entity->getPK()] = $entity->getTitle();
// $options['attributes'][$entity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $entity->getRole())];
}
$options['options'] = $tempOptions;
break;
default:
$options = parent::getFormOption($field, $options);
break;
}
return $options;
}
}

View File

@ -123,7 +123,10 @@ abstract class CommonHelper
default:
$extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' form-control' : 'form-control';
if (in_array($field, $viewDatas['formFilters'])) {
$form = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, [...$extras, ...$viewDatas['formOptions'][$field]['extras']]);
if (array_key_exists('extras', $viewDatas['formOptions'][$field])) {
$extras = array_merge($extras, $viewDatas['formOptions'][$field]['extras']);
}
$form = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, $extras);
} else {
$extras['style'] = 'width:100%;';
$form = form_input($field, $value ?? "", $extras);
@ -141,9 +144,12 @@ abstract class CommonHelper
}
break;
case 'role':
if (!is_array($value)) { //배열이 아니면
$value = explode(DEFAULTS['DELIMITER_ROLE'], $value);
}
$roles = [];
foreach ($value as $key) {
$roles[] = $viewDatas['formOptions'][$field]['options'][$key] ?? "";
$roles[] = $viewDatas['formOptions'][$field]['options'][$key];
}
$value = implode(" , ", $roles);
break;
@ -167,7 +173,7 @@ abstract class CommonHelper
break;
default:
if (in_array($field, $viewDatas['formFilters'])) {
$value = $viewDatas['formOptions'][$field]['options'][$value] ?? "";
$value = $viewDatas['formOptions'][$field]['options'][$value];
}
break;
}
@ -182,12 +188,7 @@ abstract class CommonHelper
default:
$filter = "";
if (in_array($field, $viewDatas['formFilters'])) {
$filter = form_dropdown(
$field,
$viewDatas['formOptions'][$field]['options'],
$value,
[...$extras, ...$viewDatas['formOptions'][$field]['extras']]
);
$filter = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, $extras);
}
break;
}

View File

@ -8,6 +8,30 @@ class ClientHelper extends CustomerHelper
{
parent::__construct();
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{
switch ($field) {
case 'role':
$currentRoles = is_array($value)
? array_map('strtolower', array_map('trim', $value))
: [];
$form = '';
//Form페이지에서는 맨앞에것 제외하기 위함
$firstOption = array_shift($viewDatas['formOptions'][$field]['options']);
foreach ($viewDatas['formOptions'][$field]['options'] as $key => $label) {
$checked = in_array(strtolower(trim($key)), $currentRoles);
$form .= '<label class="me-3">';
$form .= form_checkbox('role[]', $key, $checked, ['id' => "role_{$key}", ...$extras]);
$form .= " {$label}";
$form .= '</label>';
}
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) {

View File

@ -40,7 +40,7 @@ class ServiceHelper extends CustomerHelper
if (array_key_exists('unPaids', $viewDatas)) {
if (array_key_exists($viewDatas['entity']->getPK(), $viewDatas['unPaids'])) {
$value .= sprintf(
"<div><a href=\"/admin/customer/payment?serviceinfo_uid=%s\"><span style=\"color:red;\">%s개,총 %s원</span></a></div>",
"<div><a href=\"/admin/payment?serviceinfo_uid=%s\"><span style=\"color:red;\">%s개,총 %s원</span></a></div>",
$viewDatas['entity']->getPK(),
$viewDatas['unPaids'][$viewDatas['entity']->getPK()]['cnt'],
number_format($viewDatas['unPaids'][$viewDatas['entity']->getPK()]['amount'])

View File

@ -16,7 +16,7 @@
sprintf("총:%s건/%s원", $serviceCellDatas['unPaids'][$serviceEntity->getPK()]['cnt'], number_format($serviceCellDatas['unPaids'][$serviceEntity->getPK()]['amount'])),
'payment_unpaid',
[
"data-src" => "/admin/customer/payment?clientinfo_uid={$serviceEntity->getClientInfoUID()}&serviceinfo_uid={$serviceEntity->getPK()}&status=unpaid&ActionTemplate=popup",
"data-src" => "/admin/payment?clientinfo_uid={$serviceEntity->getClientInfoUID()}&serviceinfo_uid={$serviceEntity->getPK()}&status=unpaid&ActionTemplate=popup",
"data-bs-toggle" => "modal",
"data-bs-target" => "#modal_action_form",
"class" => "text-primary form-label-sm",

View File

@ -1,3 +1,6 @@
<div class="accordion-item">
<a href="/admin/user"><?= ICONS['MEMBER'] ?> 계정 관리</a>
</div>
<div class="accordion-item">
<a href="/admin/payment?status=<?= STATUS['UNPAID'] ?>"><?= ICONS['PAYMENT'] ?> 결제내역</a>
</div>

View File

@ -11,7 +11,4 @@
<div class="accordion-item">
<a href="/admin/customer/service"><?= ICONS['SERVICE'] ?> 서비스내역</a>
</div>
<div class="accordion-item">
<a href="/admin/customer/payment?status=<?= STATUS['UNPAID'] ?>"><?= ICONS['PAYMENT'] ?> 결제내역</a>
</div>
</div>