commit 4e557d4be136b67b0f3c547ac1e3fcd897acd135 Author: taekyoungc Date: Wed Mar 25 12:05:33 2026 +0900 Initial project import for team collaboration. Exclude local docs, MCP, and secrets via gitignore. Made-with: Cursor diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c16b3c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,164 @@ +#------------------------- +# Operating Specific Junk Files +#------------------------- + +# OS X +.DS_Store +.AppleDouble +.LSOverride + +# OS X Thumbnails +._* + +# Windows image file caches +Thumbs.db +ehthumbs.db +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Linux +*~ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +#------------------------- +# Environment Files +#------------------------- +# These should never be under version control, +# as it poses a security risk. +.env +.env.local +.env.*.local +.env.production +.env.staging +.env.backup +*.env.backup +!.env.example +.vagrant +Vagrantfile + +#------------------------- +# Local docs & MCP (저장소에 올리지 않음) +#------------------------- +docs/ +mcp-servers/ + +# Cursor MCP — API 키·로컬 경로 등 포함 가능 +.cursor/mcp.json + +#------------------------- +# Secrets & credentials (보안) +#------------------------- +*.pem +*.key +*.p12 +*.pfx +*.crt +*.cer +*.keystore +*.jks +id_rsa +id_rsa.pub +id_ed25519 +id_ed25519.pub +secrets/ +credentials/ +*.secret +auth.json +.aws/credentials +.netrc + +#------------------------- +# Temporary Files +#------------------------- +writable/cache/* +!writable/cache/index.html + +writable/logs/* +!writable/logs/index.html + +writable/session/* +!writable/session/index.html + +writable/uploads/* +!writable/uploads/index.html + +writable/debugbar/* +!writable/debugbar/index.html + +php_errors.log + +#------------------------- +# User Guide Temp Files +#------------------------- +user_guide_src/build/* +user_guide_src/cilexer/build/* +user_guide_src/cilexer/dist/* +user_guide_src/cilexer/pycilexer.egg-info/* + +#------------------------- +# Test Files +#------------------------- +tests/coverage* + +# Don't save phpunit under version control. +phpunit + +#------------------------- +# Composer +#------------------------- +vendor/ + +#------------------------- +# IDE / Development Files +#------------------------- + +# Modules Testing +_modules/* + +# phpenv local config +.php-version + +# Jetbrains editors (PHPStorm, etc) +.idea/ +*.iml + +# NetBeans +/nbproject/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/nbactions.xml +/nb-configuration.xml +/.nb-gradle/ + +# Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache +*.sublime-workspace +*.sublime-project +.phpintel +/api/ + +# Visual Studio Code +.vscode/ + +/results/ +/phpunit*.xml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..24728f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 British Columbia Institute of Technology +Copyright (c) 2019-present CodeIgniter Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..45f98af --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# CodeIgniter 4 Application Starter + +## What is CodeIgniter? + +CodeIgniter is a PHP full-stack web framework that is light, fast, flexible and secure. +More information can be found at the [official site](https://codeigniter.com). + +This repository holds a composer-installable app starter. +It has been built from the +[development repository](https://github.com/codeigniter4/CodeIgniter4). + +More information about the plans for version 4 can be found in [CodeIgniter 4](https://forum.codeigniter.com/forumdisplay.php?fid=28) on the forums. + +You can read the [user guide](https://codeigniter.com/user_guide/) +corresponding to the latest version of the framework. + +## Installation & updates + +`composer create-project codeigniter4/appstarter` then `composer update` whenever +there is a new release of the framework. + +When updating, check the release notes to see if there are any changes you might need to apply +to your `app` folder. The affected files can be copied or merged from +`vendor/codeigniter4/framework/app`. + +## Setup + +Copy `env` to `.env` and tailor for your app, specifically the baseURL +and any database settings. + +## Important Change with index.php + +`index.php` is no longer in the root of the project! It has been moved inside the *public* folder, +for better security and separation of components. + +This means that you should configure your web server to "point" to your project's *public* folder, and +not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the +framework are exposed. + +**Please** read the user guide for a better explanation of how CI4 works! + +## Repository Management + +We use GitHub issues, in our main repository, to track **BUGS** and to track approved **DEVELOPMENT** work packages. +We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss +FEATURE REQUESTS. + +This repository is a "distribution" one, built by our release preparation script. +Problems with it can be raised on our forum, or as issues in the main repository. + +## Server Requirements + +PHP version 8.2 or higher is required, with the following extensions installed: + +- [intl](http://php.net/manual/en/intl.requirements.php) +- [mbstring](http://php.net/manual/en/mbstring.installation.php) + +> [!WARNING] +> - The end of life date for PHP 7.4 was November 28, 2022. +> - The end of life date for PHP 8.0 was November 26, 2023. +> - The end of life date for PHP 8.1 was December 31, 2025. +> - If you are still using below PHP 8.2, you should upgrade immediately. +> - The end of life date for PHP 8.2 will be December 31, 2026. + +Additionally, make sure that the following extensions are enabled in your PHP: + +- json (enabled by default - don't turn it off) +- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php) if you plan to use MySQL +- [libcurl](http://php.net/manual/en/curl.requirements.php) if you plan to use the HTTP\CURLRequest library diff --git a/app/.htaccess b/app/.htaccess new file mode 100644 index 0000000..3462048 --- /dev/null +++ b/app/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/app/Common.php b/app/Common.php new file mode 100644 index 0000000..95f5544 --- /dev/null +++ b/app/Common.php @@ -0,0 +1,15 @@ + + */ + public array $allowedHostnames = ['jongryangje.local', 'localhost']; + + /** + * -------------------------------------------------------------------------- + * Index File + * -------------------------------------------------------------------------- + * + * Typically, this will be your `index.php` file, unless you've renamed it to + * something else. If you have configured your web server to remove this file + * from your site URIs, set this variable to an empty string. + */ + public string $indexPage = 'index.php'; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * This item determines which server global should be used to retrieve the + * URI string. The default setting of 'REQUEST_URI' works for most servers. + * If your links do not seem to work, try one of the other delicious flavors: + * + * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] + * + * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! + */ + public string $uriProtocol = 'REQUEST_URI'; + + /* + |-------------------------------------------------------------------------- + | Allowed URL Characters + |-------------------------------------------------------------------------- + | + | This lets you specify which characters are permitted within your URLs. + | When someone tries to submit a URL with disallowed characters they will + | get a warning message. + | + | As a security measure you are STRONGLY encouraged to restrict URLs to + | as few characters as possible. + | + | By default, only these are allowed: `a-z 0-9~%.:_-` + | + | Set an empty string to allow all characters -- but only if you are insane. + | + | The configured value is actually a regular expression character group + | and it will be used as: '/\A[]+\z/iu' + | + | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! + | + */ + public string $permittedURIChars = 'a-z 0-9~%.:_\-'; + + /** + * -------------------------------------------------------------------------- + * Default Locale + * -------------------------------------------------------------------------- + * + * The Locale roughly represents the language and location that your visitor + * is viewing the site from. It affects the language strings and other + * strings (like currency markers, numbers, etc), that your program + * should run under for this request. + */ + public string $defaultLocale = 'en'; + + /** + * -------------------------------------------------------------------------- + * Negotiate Locale + * -------------------------------------------------------------------------- + * + * If true, the current Request object will automatically determine the + * language to use based on the value of the Accept-Language header. + * + * If false, no automatic detection will be performed. + */ + public bool $negotiateLocale = false; + + /** + * -------------------------------------------------------------------------- + * Supported Locales + * -------------------------------------------------------------------------- + * + * If $negotiateLocale is true, this array lists the locales supported + * by the application in descending order of priority. If no match is + * found, the first locale will be used. + * + * IncomingRequest::setLocale() also uses this list. + * + * @var list + */ + public array $supportedLocales = ['en']; + + /** + * -------------------------------------------------------------------------- + * Application Timezone + * -------------------------------------------------------------------------- + * + * The default timezone that will be used in your application to display + * dates with the date helper, and can be retrieved through app_timezone() + * + * @see https://www.php.net/manual/en/timezones.php for list of timezones + * supported by PHP. + */ + public string $appTimezone = 'UTC'; + + /** + * -------------------------------------------------------------------------- + * Default Character Set + * -------------------------------------------------------------------------- + * + * This determines which character set is used by default in various methods + * that require a character set to be provided. + * + * @see http://php.net/htmlspecialchars for a list of supported charsets. + */ + public string $charset = 'UTF-8'; + + /** + * -------------------------------------------------------------------------- + * Force Global Secure Requests + * -------------------------------------------------------------------------- + * + * If true, this will force every request made to this application to be + * made via a secure connection (HTTPS). If the incoming request is not + * secure, the user will be redirected to a secure version of the page + * and the HTTP Strict Transport Security (HSTS) header will be set. + */ + public bool $forceGlobalSecureRequests = false; + + /** + * -------------------------------------------------------------------------- + * Reverse Proxy IPs + * -------------------------------------------------------------------------- + * + * If your server is behind a reverse proxy, you must whitelist the proxy + * IP addresses from which CodeIgniter should trust headers such as + * X-Forwarded-For or Client-IP in order to properly identify + * the visitor's IP address. + * + * You need to set a proxy IP address or IP address with subnets and + * the HTTP header for the client IP address. + * + * Here are some examples: + * [ + * '10.0.1.200' => 'X-Forwarded-For', + * '192.168.5.0/24' => 'X-Real-IP', + * ] + * + * @var array + */ + public array $proxyIPs = []; + + /** + * -------------------------------------------------------------------------- + * Content Security Policy + * -------------------------------------------------------------------------- + * + * Enables the Response's Content Secure Policy to restrict the sources that + * can be used for images, scripts, CSS files, audio, video, etc. If enabled, + * the Response object will populate default values for the policy from the + * `ContentSecurityPolicy.php` file. Controllers can always add to those + * restrictions at run time. + * + * For a better understanding of CSP, see these documents: + * + * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ + * @see http://www.w3.org/TR/CSP/ + */ + public bool $CSPEnabled = false; +} diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php new file mode 100644 index 0000000..9a92824 --- /dev/null +++ b/app/Config/Autoload.php @@ -0,0 +1,92 @@ +|string> + */ + public $psr4 = [ + APP_NAMESPACE => APPPATH, + ]; + + /** + * ------------------------------------------------------------------- + * Class Map + * ------------------------------------------------------------------- + * The class map provides a map of class names and their exact + * location on the drive. Classes loaded in this manner will have + * slightly faster performance because they will not have to be + * searched for within one or more directories as they would if they + * were being autoloaded through a namespace. + * + * Prototype: + * $classmap = [ + * 'MyClass' => '/path/to/class/file.php' + * ]; + * + * @var array + */ + public $classmap = []; + + /** + * ------------------------------------------------------------------- + * Files + * ------------------------------------------------------------------- + * The files array provides a list of paths to __non-class__ files + * that will be autoloaded. This can be useful for bootstrap operations + * or for loading functions. + * + * Prototype: + * $files = [ + * '/path/to/my/file.php', + * ]; + * + * @var list + */ + public $files = []; + + /** + * ------------------------------------------------------------------- + * Helpers + * ------------------------------------------------------------------- + * Prototype: + * $helpers = [ + * 'form', + * ]; + * + * @var list + */ + public $helpers = []; +} diff --git a/app/Config/Boot/development.php b/app/Config/Boot/development.php new file mode 100644 index 0000000..a868447 --- /dev/null +++ b/app/Config/Boot/development.php @@ -0,0 +1,34 @@ + + * + * @see https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect + */ + public array $shareConnectionOptions = [ + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_DNS, + ]; + + /** + * -------------------------------------------------------------------------- + * CURLRequest Share Options + * -------------------------------------------------------------------------- + * + * Whether share options between requests or not. + * + * If true, all the options won't be reset between requests. + * It may cause an error request with unnecessary headers. + */ + public bool $shareOptions = false; +} diff --git a/app/Config/Cache.php b/app/Config/Cache.php new file mode 100644 index 0000000..38ac541 --- /dev/null +++ b/app/Config/Cache.php @@ -0,0 +1,198 @@ + WRITEPATH . 'cache/', + 'mode' => 0640, + ]; + + /** + * ------------------------------------------------------------------------- + * Memcached settings + * ------------------------------------------------------------------------- + * + * Your Memcached servers can be specified below, if you are using + * the Memcached drivers. + * + * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached + * + * @var array{host?: string, port?: int, weight?: int, raw?: bool} + */ + public array $memcached = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 1, + 'raw' => false, + ]; + + /** + * ------------------------------------------------------------------------- + * Redis settings + * ------------------------------------------------------------------------- + * + * Your Redis server can be specified below, if you are using + * the Redis or Predis drivers. + * + * @var array{ + * host?: string, + * password?: string|null, + * port?: int, + * timeout?: int, + * async?: bool, + * persistent?: bool, + * database?: int + * } + */ + public array $redis = [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'async' => false, // specific to Predis and ignored by the native Redis extension + 'persistent' => false, + 'database' => 0, + ]; + + /** + * -------------------------------------------------------------------------- + * Available Cache Handlers + * -------------------------------------------------------------------------- + * + * This is an array of cache engine alias' and class names. Only engines + * that are listed here are allowed to be used. + * + * @var array> + */ + public array $validHandlers = [ + 'apcu' => ApcuHandler::class, + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, + 'memcached' => MemcachedHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, + ]; + + /** + * -------------------------------------------------------------------------- + * Web Page Caching: Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * ['q'] = Enabled, but only take into account the specified list + * of query parameters. + * + * @var bool|list + */ + public $cacheQueryString = false; + + /** + * -------------------------------------------------------------------------- + * Web Page Caching: Cache Status Codes + * -------------------------------------------------------------------------- + * + * HTTP status codes that are allowed to be cached. Only responses with + * these status codes will be cached by the PageCache filter. + * + * Default: [] - Cache all status codes (backward compatible) + * + * Recommended: [200] - Only cache successful responses + * + * You can also use status codes like: + * [200, 404, 410] - Cache successful responses and specific error codes + * [200, 201, 202, 203, 204] - All 2xx successful responses + * + * WARNING: Using [] may cache temporary error pages (404, 500, etc). + * Consider restricting to [200] for production applications to avoid + * caching errors that should be temporary. + * + * @var list + */ + public array $cacheStatusCodes = []; +} diff --git a/app/Config/Constants.php b/app/Config/Constants.php new file mode 100644 index 0000000..fb56bb1 --- /dev/null +++ b/app/Config/Constants.php @@ -0,0 +1,79 @@ +|string|null + */ + public $defaultSrc; + + /** + * Lists allowed scripts' URLs. + * + * @var list|string + */ + public $scriptSrc = 'self'; + + /** + * Specifies valid sources for JavaScript + + + + + +
+
+ + +
+ +
+
+ +
+getFlashdata('success')): ?> + + +getFlashdata('error')): ?> + + +getFlashdata('errors')): ?> + + +
+ +
+
+ 쓰레기봉투 물류시스템 관리자 + +
+ + diff --git a/app/Views/admin/local_government/create.php b/app/Views/admin/local_government/create.php new file mode 100644 index 0000000..2225cf9 --- /dev/null +++ b/app/Views/admin/local_government/create.php @@ -0,0 +1,40 @@ +
+ 지자체 등록 +
+
+
+ + +
+ + +
+ +
+ + + 행정 코드 등 식별용 +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + 목록 +
+
+
+ diff --git a/app/Views/admin/local_government/index.php b/app/Views/admin/local_government/index.php new file mode 100644 index 0000000..bccfd47 --- /dev/null +++ b/app/Views/admin/local_government/index.php @@ -0,0 +1,35 @@ +
+
+ 지자체 목록 + 지자체 등록 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
번호지자체명코드시/도구/군상태등록일
lg_idx) ?>lg_name) ?>lg_code) ?>lg_sido) ?>lg_gugun) ?>lg_state === 1 ? '사용' : '미사용' ?>lg_regdate ?? '') ?>
+
+ diff --git a/app/Views/admin/menu/index.php b/app/Views/admin/menu/index.php new file mode 100644 index 0000000..19827fd --- /dev/null +++ b/app/Views/admin/menu/index.php @@ -0,0 +1,469 @@ + +
+
+ 메뉴 관리 +
+ +
+ + +
+ +
+
+
+ +
+
+

메뉴 목록

+ +

메뉴 종류를 선택하세요.

+ +

등록된 메뉴가 없습니다. 아래에서 등록하세요.

+ +
+ +
+

메뉴 등록

+ +
+
+ + + + diff --git a/app/Views/admin/role/index.php b/app/Views/admin/role/index.php new file mode 100644 index 0000000..79f8e3a --- /dev/null +++ b/app/Views/admin/role/index.php @@ -0,0 +1,22 @@ +
+ 역할 (mb_level) +
+
+

Config\Roles 기반 역할 목록입니다.

+ + + + + + + + + levelNames as $code => $name): ?> + + + + + + +
코드이름
+
diff --git a/app/Views/admin/select_local_government/index.php b/app/Views/admin/select_local_government/index.php new file mode 100644 index 0000000..686be71 --- /dev/null +++ b/app/Views/admin/select_local_government/index.php @@ -0,0 +1,21 @@ +
+

관리자 페이지에서 사용할 지자체를 선택하세요. 선택한 지자체 기준으로 목록·등록이 표시됩니다.

+
+
+ +

등록된 지자체가 없습니다. 지자체 관리에서 먼저 등록하세요.

+ +
+ +
    + +
  • + + +
  • + +
+ +
+ +
diff --git a/app/Views/admin/user/create.php b/app/Views/admin/user/create.php new file mode 100644 index 0000000..1d4e793 --- /dev/null +++ b/app/Views/admin/user/create.php @@ -0,0 +1,40 @@ +
+ 회원 등록 +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + 목록 +
+
+
diff --git a/app/Views/admin/user/edit.php b/app/Views/admin/user/edit.php new file mode 100644 index 0000000..818ac90 --- /dev/null +++ b/app/Views/admin/user/edit.php @@ -0,0 +1,48 @@ +
+ 회원 수정 +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + 목록 +
+
+
diff --git a/app/Views/admin/user/index.php b/app/Views/admin/user/index.php new file mode 100644 index 0000000..b349c87 --- /dev/null +++ b/app/Views/admin/user/index.php @@ -0,0 +1,55 @@ +
+
+ 회원 목록 + 회원 등록 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호아이디이름이메일역할상태가입일관리
mb_idx) ?>mb_id) ?>mb_name) ?>mb_email ?? '') ?>getLevelName((int) $row->mb_level)) ?> + mb_idx] ?? null; + if ($approvalStatus === 'pending') { + echo '승인대기'; + } elseif ($approvalStatus === 'rejected') { + echo '승인반려'; + } else { + echo ((int) $row->mb_state === 1 ? '정상' : ((int) $row->mb_state === 2 ? '정지' : '탈퇴')); + } + ?> + mb_regdate ?? '') ?> + mb_state !== 0): ?> + 수정 +
+ + +
+ +
+
diff --git a/app/Views/auth/login.php b/app/Views/auth/login.php new file mode 100644 index 0000000..ecf3cc7 --- /dev/null +++ b/app/Views/auth/login.php @@ -0,0 +1,73 @@ + + + + + +로그인 - 쓰레기봉투 물류시스템 + + + + + + +
+ +
+
+ 로그인 +
+getFlashdata('success')): ?> + + +getFlashdata('error')): ?> + + +getFlashdata('errors')): ?> + + +
+
+
+ +
+ + +
+
+ + +
+
+ + 회원가입 +
+
+
+
+
쓰레기봉투 물류시스템
+ + diff --git a/app/Views/auth/register.php b/app/Views/auth/register.php new file mode 100644 index 0000000..659f141 --- /dev/null +++ b/app/Views/auth/register.php @@ -0,0 +1,107 @@ + + + + + +회원가입 - 쓰레기봉투 물류시스템 + + + + + + +
+ +
+
+ 회원가입 +
+getFlashdata('error')): ?> + + +getFlashdata('errors')): ?> + + +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +

가입 후 관리자 승인 완료 시 로그인할 수 있습니다.

+
+
+ + 로그인 +
+
+
+
+
쓰레기봉투 물류시스템
+ + diff --git a/app/Views/bag/daily_inventory.php b/app/Views/bag/daily_inventory.php new file mode 100644 index 0000000..5934621 --- /dev/null +++ b/app/Views/bag/daily_inventory.php @@ -0,0 +1,637 @@ + + + + + + +쓰레기봉투 물류시스템 + + + + + + + + + + + +
+
+ + +
+ + +get('mb_level'); +$isAdmin = ($mbLevel === \Config\Roles::LEVEL_SUPER_ADMIN || $mbLevel === \Config\Roles::LEVEL_LOCAL_ADMIN); +?> + + +
+ +getFlashdata('success')): ?> + + + +
+[w_gm804r] +일일 봉투 수불 현황 +
+ + +
+
+ +
+
+ +
+ +~ + + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + + + 종료 + +
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
일자품 목전일재고입고출고잔량
입고반품입고계판매일반불출/무료불출반품기타출고계
2024.01.01일반용 5L187,2400000187,240
일반용 5L000000
일반용 10L159,428252,000252,8008,5808,5808,990402,848
일반용 20L212,082201,000201,60011,32011,32011,320402,365
일반용 50L7,60513,00013,00054054054020,065
일반용 75L31,45922,60022,6002,9902,0903,64086,240
일반용 100L1100011
일반용 70L77,40001,0001,0001,00076,400
공동주택용 20L0000
공동주택용 50L0000
공동주택용 120L11000
재사용 봉투58,54027,00027,00056056056084,990
음식물 2L0000
음식물 스티커 1L376,7580100100180376,658
음식물 스티커 2L231,5420100100100231,422
음식물 스티커 3L529,93801,2001,2001,200529,738
음식물 스티커 70L751,03601,4001,4001,400750,030
음식물 스티커 60L00006
음식물 스티커 120L209,7430808080209,663
폐기물 스티커 1,000원161,6760300300300161,376
폐기물 스티커 3,000원98,018012012012097,999
폐기물 스티커 5,000원61,631040404061,591
2024.01.03폐기물 스티커 10,000원44,86000044,860
일반용 5L187,240000187,240
일반용 10L402,848000402,848
일반용 10L402,365000402,365
+
+
+ + +
+
Ready.....
+
+북구 +Ver.. +2025.12.12 (금) 3:00:32PM +
+
+ + + diff --git a/app/Views/bag/inventory_inquiry.php b/app/Views/bag/inventory_inquiry.php new file mode 100644 index 0000000..6b23226 --- /dev/null +++ b/app/Views/bag/inventory_inquiry.php @@ -0,0 +1,347 @@ + + + + + + 스마트 폐기물 관리 시스템 - 재고 관리 + + + + + + +
+
+
+ +
+

스마트 폐기물 관리 시스템

+
+
+ +
+
+ + +
+ + + + + +
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
품목전일재고입고출고잔량
입고반품입고계판매임의불출/무상불출반품기타출고계
일반용 5L187,2400000187,240
일반용 5L000000
일반용 10L159,428252,000252,8008,5808,5808,990402,848
일반용 20L212,082201,000201,60011,32011,32011,320402,355
일반용 50L7,60513,00013,00054054054020,065
일반용 75L31,45922,60022,6002,9902,0903,64086,240
일반용 100L1100011
일반용 70L77,40001,0001,0001,00076,400
공동주택용 20L00000
공동주택용 50L00000
재사용 봉투58,54027,00027,00056056056084,990
+
+
+ +
+ +
+ + +
+
Ready.....
+
+ 북구 + Ver.. + 2025.12.12 (금) 3:00:32PM +
+
+ + + diff --git a/app/Views/bag/lg_dashboard.php b/app/Views/bag/lg_dashboard.php new file mode 100644 index 0000000..7e99102 --- /dev/null +++ b/app/Views/bag/lg_dashboard.php @@ -0,0 +1,282 @@ +get('mb_name') ?? '담당자'; +?> + + + + + + 종량제 시스템 — 업무 현황 + + + + + + +
+ +
+ +
+ +
+ + 업무 현황 대시보드 + · 봉투 재고 · 구매신청 · 발주/승인 요약 + +
+ + +
+
+ + +
+
+
+ 기준일 + + | + 지자체 + +
+

목업 데이터 · 연동 시 실시간 반영

+
+
+ +
+ getFlashdata('success')): ?> +
getFlashdata('success')) ?>
+ + + +
+
+

재고 부족 품목

+

3

+

안전재고 미만 봉투 종류

+
+
+

미처리 구매신청

+

12

+

지정판매소 · 금일 기준

+
+
+

이번 주 발주·입고

+

8

+

발주 5 · 입고완료 3

+
+
+

승인 대기 회원

+

4

+

가입·권한 승인 요청

+
+
+ +
+
+
+

봉투별 재고 현황

+ 낱장 환산 · 목업 +
+ '일반용 5L', 'pct' => 92], + ['label' => '일반용 10L', 'pct' => 78], + ['label' => '일반용 20L', 'pct' => 65], + ['label' => '음식물 스티커', 'pct' => 41], + ['label' => '재사용 봉투', 'pct' => 88], + ]; + foreach ($stockRows as $r): + ?> +
+
+ + % +
+
+
+
+
+ +
+ +
+
+

최근 7일 구매신청·처리 추이

+ 건수 +
+
+ $v): + $h = $max > 0 ? round(($v / $max) * 100) : 0; + ?> +
+ +
+ D- +
+ +
+

일별 신청 건수 · 처리 연동 예정

+
+
+ +
+
+

지정판매소 구매신청 (최근)

+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
신청일시판매소품목수량상태
+ + +
+
+
+ +
+
+

이번 주 발주·입고 요약

+
    +
  • 발주 접수5건
  • +
  • 입고 완료3건
  • +
  • 입고 예정(LOT)2건
  • +
+
+
+

승인 대기 회원

+

4

+

지정판매소 · 일반 가입

+ +
+
+

최근 7일 봉투 수불 추이

+

입고 +482 / 출고 −391

+
+ +
+ +
+
+
+ +

+ 차장님 요청 반영: 봉투별 재고·구매신청 리스트·그래프 / + 추가 시안: 발주·입고, 승인 대기, 수불 추이. + 레이아웃은 수불 엔터프라이즈 화면과 동일한 상단 메뉴·제목바 스타일입니다. +

+
+
+ +
+
+ 준비됨 + | + +
+
+ Ver. 목업 + +
+
+ + diff --git a/app/Views/bag/lg_dashboard_charts.php b/app/Views/bag/lg_dashboard_charts.php new file mode 100644 index 0000000..9f4e578 --- /dev/null +++ b/app/Views/bag/lg_dashboard_charts.php @@ -0,0 +1,429 @@ +get('mb_name') ?? '담당자'; +$dashClassic = base_url('dashboard/classic-mock'); +$dashModern = base_url('dashboard/modern'); +$dashDense = base_url('dashboard/dense'); +$dashCharts = base_url('dashboard/charts'); +?> + + + + + + 종량제 시스템 — 통계·그래프 현황 + + + + + + +
+ +
+ +
+ + 통계·그래프 대시보드 + · 목업 데이터 · Chart.js + + · +
+ +
+ getFlashdata('success')): ?> +
getFlashdata('success')) ?>
+ + + +
+
+

봉투 규격 출고 비중

+
+
+
+

구매신청 처리 단계

+
+
+
+

금주 일별 출고(천장)

+
+
+
+

운영 지표 (목업)

+
+
+
+ + +
+

월별 출고 vs 구매신청 건수 (최근 12개월)

+
+
+ + +
+
+

품목별 재고 (천 장)

+
+
+
+

판매소별 월 출고 TOP

+
+
+
+ + +
+

분기별 입고 / 출고 / 조정 (천 장)

+
+
+ + +
+
+

누적 출고 추이 (올해)

+
+
+
+

요일·시간대 신청 분포 (극좌표)

+
+
+
+ +

+ /dashboard + · /dashboard/modern + · /dashboard/dense + · /dashboard/charts +

+
+ + + + diff --git a/app/Views/bag/lg_dashboard_dense.php b/app/Views/bag/lg_dashboard_dense.php new file mode 100644 index 0000000..85179c5 --- /dev/null +++ b/app/Views/bag/lg_dashboard_dense.php @@ -0,0 +1,391 @@ +get('mb_name') ?? '담당자'; +$dashClassic = base_url('dashboard/classic-mock'); +$dashModern = base_url('dashboard/modern'); +$dashDense = base_url('dashboard/dense'); +$dashCharts = base_url('dashboard/charts'); + +$kpiTop = [ + ['icon' => 'fa-triangle-exclamation', 'c' => 'text-amber-700', 'bg' => 'bg-amber-50', 'v' => '3', 'l' => '재고부족', 'sub' => '품목'], + ['icon' => 'fa-cart-shopping', 'c' => 'text-sky-700', 'bg' => 'bg-sky-50', 'v' => '12', 'l' => '구매신청', 'sub' => '미처리'], + ['icon' => 'fa-truck', 'c' => 'text-emerald-700', 'bg' => 'bg-emerald-50', 'v' => '8', 'l' => '발주·입고', 'sub' => '금주'], + ['icon' => 'fa-user-clock', 'c' => 'text-violet-700', 'bg' => 'bg-violet-50', 'v' => '4', 'l' => '회원승인', 'sub' => '대기'], + ['icon' => 'fa-store', 'c' => 'text-rose-700', 'bg' => 'bg-rose-50', 'v' => '127', 'l' => '지정판매소', 'sub' => '등록'], + ['icon' => 'fa-boxes-stacked', 'c' => 'text-slate-700', 'bg' => 'bg-slate-100', 'v' => '48.2k', 'l' => '봉투재고', 'sub' => '장 합계'], + ['icon' => 'fa-file-invoice', 'c' => 'text-orange-700', 'bg' => 'bg-orange-50', 'v' => '6', 'l' => '세금계산서', 'sub' => '발행대기'], + ['icon' => 'fa-headset', 'c' => 'text-cyan-700', 'bg' => 'bg-cyan-50', 'v' => '2', 'l' => '민원·문의', 'sub' => '오늘'], +]; + +$stockRows = [ + ['일반 5L', '12,400', '안전', '3.2주'], + ['일반 10L', '8,200', '주의', '1.8주'], + ['일반 20L', '2,100', '부족', '0.6주'], + ['음식물 스티커', '15,000', '안전', '5.1주'], + ['재사용봉투', '4,300', '안전', '2.4주'], + ['특수규격 A', '890', '부족', '0.3주'], +]; + +$orderRows = [ + ['PO-2025-0218', '○○상사', '일반 5L×2박스', '발주확인', '02-26 10:20'], + ['PO-2025-0217', '△△유통', '스티커 500매', '납품중', '02-26 09:05'], + ['PO-2025-0216', '□□종량제', '20L 혼합', '입고완료', '02-25 16:40'], + ['REQ-8841', '행복마트 북구점', '5L 2,000장', '접수', '02-26 09:12'], + ['REQ-8839', '○○슈퍼', '스티커 500', '처리중', '02-26 08:45'], +]; + +$logRows = [ + ['10:42', 'system', '일일 재고 스냅샷 생성 완료'], + ['10:18', 'user', esc($mbName) . ' 로그인 (IP 마스킹)'], + ['09:55', 'batch', '구매신청 자동 분배 3건'], + ['09:30', 'admin', '판매소 코드 2건 갱신'], + ['08:12', 'api', '세금계산서 연동 응답 정상'], +]; + +$storeSummary = [ + ['행복마트 북구점', '42', '정상', '02-26'], + ['○○슈퍼', '38', '정상', '02-25'], + ['△△상회', '15', '연체1건', '02-20'], + ['□□마트', '29', '정상', '02-26'], + ['◇◇할인점', '51', '정상', '02-26'], +]; + +$approvals = [ + ['김○○', '판매소', '02-26', '서류검토'], + ['이○○', '일반', '02-25', '본인확인'], + ['박○○', '판매소', '02-25', '주소불일치'], +]; + +$notices = [ + '2월 말 정기 재고 실사 안내 — 2/28 17:00 마감', + '봉투 단가 조정 예고 — 3/1 적용 예정 (안내문 배포 완료)', +]; +?> + + + + + + 종량제 시스템 — 종합 현황 (정보집약) + + + + + +
+ +
+ + +
+ + 종합 운영 현황 + · KPI · 재고 · 발주/신청 · 로그 · 판매소 + +
+ + | + 기준지자체 + +
+
+ +
+ getFlashdata('success')): ?> +
getFlashdata('success')) ?>
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+
+ +
+
+
+
+
+
+
+ +
+ +
+ +
+
+

품목별 재고·소진예상

+ 상세 +
+
+ + + + + + + + + + + + + + + + + + + +
품목재고(장)상태소진
+ 'bg-emerald-100 text-emerald-800', + '주의' => 'bg-amber-100 text-amber-800', + '부족' => 'bg-red-100 text-red-800', + default => 'bg-gray-100 text-gray-700', + }; + ?> + +
+
+
+ + +
+
+

발주 / 구매신청 진행

+ 최근 5건 +
+
+ + + + + + + + + + + + + + + + + + + + + +
문서상대내용단계시각
+
+
+ + +
+
+

최근 이벤트 로그

+
+
    + +
  • + + + +
  • + +
+
+
주간 봉투 출고(천 장, 목업)
+
+ + + +
+
+ +
+
+
+
+ +
+ +
+
+

지정판매소 요약

+ 상위 5곳 +
+ + + + + + + + + + + + + + + + + + + +
판매소명월 봉투(백장)상태최종거래
+ + + + + +
+
+ + +
+
+

회원·판매소 승인 대기

+
+
+
+
4
+
전체 대기
+
+
+
2
+
오늘 접수
+
+
+
1.2일
+
평균 처리
+
+
+ + + + + + + + + + + + + + + + + + + +
신청자유형접수일메모
+
+
+ + +
+
+
+
비중
+
+
+
일반 40%
+
스티커 30%
+
대형/특수 22%
+
+
+
+

운영 브리핑 (목업)

+
    +
  • 다음 주 예상 구매신청 약 28건 (전주 대비 +12%)
  • +
  • 일반 20L·특수규격 A 발주 권고 — 안전재고 미달
  • +
  • 세금계산서 6건 미발행 — 담당 회계에 알림 발송됨
  • +
  • 지정판매소 △△상회 연체 1건 — 현장 점검 일정 3/3
  • +
+
+
+ +

+ 레이아웃: /dashboard + · /dashboard/modern + · /dashboard/dense (이 화면) + · /dashboard/charts +

+
+ + diff --git a/app/Views/bag/lg_dashboard_modern.php b/app/Views/bag/lg_dashboard_modern.php new file mode 100644 index 0000000..f0e7836 --- /dev/null +++ b/app/Views/bag/lg_dashboard_modern.php @@ -0,0 +1,215 @@ +get('mb_name') ?? '담당자'; +$dashClassic = base_url('dashboard/classic-mock'); +$dashModern = base_url('dashboard/modern'); +$dashDense = base_url('dashboard/dense'); +$dashCharts = base_url('dashboard/charts'); +?> + + + + + + 종량제 시스템 — 업무 현황 (모던) + + + + + + + +
+ +
+ +
+ getFlashdata('success')): ?> +
getFlashdata('success')) ?>
+ + + +
+
+
+

+

안녕하세요,

+

오늘의 재고·구매신청·발주 요약을 한눈에 확인하세요. 다른 레이아웃은 가로 메뉴형 대시보드에서 볼 수 있습니다.

+
+
+ + +
+
+
+

3

+

재고 부족 품목

+
+
+
+

12

+

미처리 구매신청

+
+
+
+

8

+

이번 주 발주·입고

+
+
+
+

4

+

승인 대기 회원

+
+
+ +
+ +
+

봉투 재고 비중

+
+
+
+ 100% + 목업 +
+
+
    +
  • 일반용
  • +
  • 스티커
  • +
  • 재사용
  • +
  • 기타
  • +
+
+
+ +
+
+

지정판매소 구매신청

+ +
+
    + +
  • + +
    +
    + + +
    +

    + +
    +
  • + +
+
+
+ + +
+
+

최근 신청 상세

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
일시판매소품목수량상태
2025-02-26 09:12행복마트 북구점일반용 5L2,000장접수
2025-02-26 08:45○○슈퍼음식물 스티커500장처리중
+
+
+ +

+ URL 비교 — 클래식 레이아웃 /dashboard + · 모던 콘텐츠(이 화면) /dashboard/modern + · /dashboard/charts + · 상단 메뉴는 동일 +

+
+ + diff --git a/app/Views/bag/waste_suibal_enterprise.php b/app/Views/bag/waste_suibal_enterprise.php new file mode 100644 index 0000000..e31a81c --- /dev/null +++ b/app/Views/bag/waste_suibal_enterprise.php @@ -0,0 +1,446 @@ + + + + + + 종량제 시스템 — 봉투 수불 현황 + + + + + + +
+ +
+ +
+
+ 봉투 수불 현황 (기간·품목별) + +
+ +
+
+
+
+ + + ~ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
일자품목전월재고입고입고
소계
출고
소계
출고잔량
입고반품기타판매기타합계
2024.01.01일반형 5L187,2400000187,240
일반형 5L000000
일반형 10L159,428252,000252,0008,5808,5808,990402,248
일반형 20L212,082201,000201,60011,32011,32011,320402,365
일반형 50L7,60513,00013,00054054054020,065
일반형 75L31,45922,60022,6002,9902,0903,64086,240
일반형 100L1100011
할인용 70L77,40001,0001,0001,00076,400
공공용(매립) 20L0000
공공용(매립) 50L0000
재사용 백58,54027,00027,00056056056084,990
음식물 2L0000
음식물 스티커 1L376,7580100100180376,658
음식물 스티커 2L231,5420100100100231,422
음식물 스티커 3L529,93801,2001,2001,200529,738
음식물 스티커 70L751,03601,4001,4001,400750,030
대형용 스티커 120L209,7430808080209,663
폐기물 스티커 1,000원161,6760300300300161,376
2024.01.03폐기물 스티커 10,000원44,86000044,860
일반형 5L187,240000187,240
일반형 10L402,848000402,848
일반형 20L402,365000402,365
+
+
+ +
+
준비됨
+
+ 북구 + Ver. 목업 + +
+
+ + diff --git a/app/Views/errors/cli/error_404.php b/app/Views/errors/cli/error_404.php new file mode 100644 index 0000000..456ea3e --- /dev/null +++ b/app/Views/errors/cli/error_404.php @@ -0,0 +1,7 @@ +getFile()) . ':' . $exception->getLine(), 'green')); +CLI::newLine(); + +$last = $exception; + +while ($prevException = $last->getPrevious()) { + $last = $prevException; + + CLI::write(' Caused by:'); + CLI::write(' [' . $prevException::class . ']', 'red'); + CLI::write(' ' . $prevException->getMessage()); + CLI::write(' at ' . CLI::color(clean_path($prevException->getFile()) . ':' . $prevException->getLine(), 'green')); + CLI::newLine(); +} + +// The backtrace +if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) { + $backtraces = $last->getTrace(); + + if ($backtraces) { + CLI::write('Backtrace:', 'green'); + } + + foreach ($backtraces as $i => $error) { + $padFile = ' '; // 4 spaces + $padClass = ' '; // 7 spaces + $c = str_pad($i + 1, 3, ' ', STR_PAD_LEFT); + + if (isset($error['file'])) { + $filepath = clean_path($error['file']) . ':' . $error['line']; + + CLI::write($c . $padFile . CLI::color($filepath, 'yellow')); + } else { + CLI::write($c . $padFile . CLI::color('[internal function]', 'yellow')); + } + + $function = ''; + + if (isset($error['class'])) { + $type = ($error['type'] === '->') ? '()' . $error['type'] : $error['type']; + $function .= $padClass . $error['class'] . $type . $error['function']; + } elseif (! isset($error['class']) && isset($error['function'])) { + $function .= $padClass . $error['function']; + } + + $args = implode(', ', array_map(static fn ($value): string => match (true) { + is_object($value) => 'Object(' . $value::class . ')', + is_array($value) => $value !== [] ? '[...]' : '[]', + $value === null => 'null', // return the lowercased version + default => var_export($value, true), + }, array_values($error['args'] ?? []))); + + $function .= '(' . $args . ')'; + + CLI::write($function); + CLI::newLine(); + } +} diff --git a/app/Views/errors/cli/production.php b/app/Views/errors/cli/production.php new file mode 100644 index 0000000..7db744e --- /dev/null +++ b/app/Views/errors/cli/production.php @@ -0,0 +1,5 @@ + + + + + <?= lang('Errors.badRequest') ?> + + + + +
+

400

+ +

+ + + + + +

+
+ + diff --git a/app/Views/errors/html/error_404.php b/app/Views/errors/html/error_404.php new file mode 100644 index 0000000..e506f08 --- /dev/null +++ b/app/Views/errors/html/error_404.php @@ -0,0 +1,84 @@ + + + + + <?= lang('Errors.pageNotFound') ?> + + + + +
+

404

+ +

+ + + + + +

+
+ + diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php new file mode 100644 index 0000000..2c4e009 --- /dev/null +++ b/app/Views/errors/html/error_exception.php @@ -0,0 +1,429 @@ + + + + + + + + <?= esc($title) ?> + + + + + + + +
+
+ Displayed at — + PHP: — + CodeIgniter: -- + Environment: +
+
+

getCode() ? ' #' . $exception->getCode() : '') ?>

+

+ getMessage())) ?> + getMessage())) ?>" + rel="noreferrer" target="_blank">search → +

+
+
+ + +
+

at line

+ + +
+ +
+ +
+ +
+ getPrevious()) { + $last = $prevException; + ?> + +
+    Caused by:
+    getCode() ? ' #' . $prevException->getCode() : '') ?>
+
+    getMessage())) ?>
+    getMessage())) ?>"
+       rel="noreferrer" target="_blank">search →
+    getFile()) . ':' . $prevException->getLine()) ?>
+    
+ + +
+ + +
+ + + +
+ + +
+ +
    + $row) : ?> + +
  1. +

    + + + + + {PHP internal code} + + + + +   —   + + + ( arguments ) +

    + + + getParameters(); + } + + foreach ($row['args'] as $key => $value) : ?> + + + + + + +
    name : "#{$key}") ?>
    +
    + + () + + + + +   —   () + +

    + + + +
    + +
    + +
  2. + + +
+ +
+ + +
+ + + +

$

+ + + + + + + + + + $value) : ?> + + + + + + +
KeyValue
+ + + +
+ +
+ + + + + + +

Constants

+ + + + + + + + + + $value) : ?> + + + + + + +
KeyValue
+ + + +
+ +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathgetUri()) ?>
HTTP MethodgetMethod()) ?>
IP AddressgetIPAddress()) ?>
Is AJAX Request?isAJAX() ? 'yes' : 'no' ?>
Is CLI Request?isCLI() ? 'yes' : 'no' ?>
Is Secure Request?isSecure() ? 'yes' : 'no' ?>
User AgentgetUserAgent()->getAgentString()) ?>
+ + + + + + + + +

$

+ + + + + + + + + + $value) : ?> + + + + + + +
KeyValue
+ + + +
+ +
+ + + + + +
+ No $_GET, $_POST, or $_COOKIE Information to show. +
+ + + + headers(); ?> + + +

Headers

+ + + + + + + + + + $value) : ?> + + + + + + +
HeaderValue
+ getValueLine(), 'html'); + } else { + foreach ($value as $i => $header) { + echo ' ('. $i+1 . ') ' . esc($header->getValueLine(), 'html'); + } + } + ?> +
+ + +
+ + + setStatusCode(http_response_code()); + ?> +
+ + + + + +
Response StatusgetStatusCode() . ' - ' . $response->getReasonPhrase()) ?>
+ + headers(); ?> + +

Headers

+ + + + + + + + + + $value) : ?> + + + + + + +
HeaderValue
+ getHeaderLine($name), 'html'); + } else { + foreach ($value as $i => $header) { + echo ' ('. $i+1 . ') ' . esc($header->getValueLine(), 'html'); + } + } + ?> +
+ + +
+ + +
+ + +
    + +
  1. + +
+
+ + +
+ + + + + + + + + + + + + + + + +
Memory Usage
Peak Memory Usage:
Memory Limit:
+ +
+ +
+ +
+ + + + diff --git a/app/Views/errors/html/production.php b/app/Views/errors/html/production.php new file mode 100644 index 0000000..2f59a8d --- /dev/null +++ b/app/Views/errors/html/production.php @@ -0,0 +1,25 @@ + + + + + + + <?= lang('Errors.whoops') ?> + + + + + +
+ +

+ +

+ +
+ + + + diff --git a/app/Views/home/dashboard.php b/app/Views/home/dashboard.php new file mode 100644 index 0000000..e442dff --- /dev/null +++ b/app/Views/home/dashboard.php @@ -0,0 +1,56 @@ + + + + + +홈 - 쓰레기봉투 물류시스템 + + + + + + +
+ + + 종료 + +
+
+ 홈 +
+getFlashdata('success')): ?> + + +
+
+

get('mb_name')) ?>님, 환영합니다.

+

아이디: get('mb_id')) ?>

+

역할: getLevelName((int) session()->get('mb_level'))) ?>

+ 로그아웃 +
+
+
쓰레기봉투 물류시스템
+ + diff --git a/app/Views/welcome_message.php b/app/Views/welcome_message.php new file mode 100644 index 0000000..180a670 --- /dev/null +++ b/app/Views/welcome_message.php @@ -0,0 +1,56 @@ + + + + + +쓰레기봉투 물류시스템 + + + + + + +
+ + +
+
+ 쓰레기봉투 물류시스템 +
+
+
+

로그인 후 이용해 주세요.

+ +
+
+
쓰레기봉투 물류시스템
+ + diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..69df4e1 --- /dev/null +++ b/app/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/builds b/builds new file mode 100755 index 0000000..cc2ca08 --- /dev/null +++ b/builds @@ -0,0 +1,125 @@ +#!/usr/bin/env php + 'vcs', + 'url' => GITHUB_URL, + ]; + } + + $array['require']['codeigniter4/codeigniter4'] = 'dev-develop'; + unset($array['require']['codeigniter4/framework']); + } else { + unset($array['minimum-stability']); + + if (isset($array['repositories'])) { + foreach ($array['repositories'] as $i => $repository) { + if ($repository['url'] === GITHUB_URL) { + unset($array['repositories'][$i]); + break; + } + } + + if (empty($array['repositories'])) { + unset($array['repositories']); + } + } + + $array['require']['codeigniter4/framework'] = LATEST_RELEASE; + unset($array['require']['codeigniter4/codeigniter4']); + } + + file_put_contents($file, json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL); + + $modified[] = $file; + } else { + echo 'Warning: Unable to decode composer.json! Skipping...' . PHP_EOL; + } + } else { + echo 'Warning: Unable to read composer.json! Skipping...' . PHP_EOL; + } +} + +$files = [ + __DIR__ . DIRECTORY_SEPARATOR . 'app/Config/Paths.php', + __DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml.dist', + __DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml', +]; + +foreach ($files as $file) { + if (is_file($file)) { + $contents = file_get_contents($file); + + if ($dev) { + $contents = str_replace('vendor/codeigniter4/framework', 'vendor/codeigniter4/codeigniter4', $contents); + } else { + $contents = str_replace('vendor/codeigniter4/codeigniter4', 'vendor/codeigniter4/framework', $contents); + } + + file_put_contents($file, $contents); + + $modified[] = $file; + } +} + +if ($modified === []) { + echo 'No files modified.' . PHP_EOL; +} else { + echo 'The following files were modified:' . PHP_EOL; + + foreach ($modified as $file) { + echo " * {$file}" . PHP_EOL; + } + + echo 'Run `composer update` to sync changes with your vendor folder.' . PHP_EOL; +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d47149e --- /dev/null +++ b/composer.json @@ -0,0 +1,43 @@ +{ + "name": "codeigniter4/appstarter", + "description": "CodeIgniter4 starter app", + "license": "MIT", + "type": "project", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + }, + "require": { + "php": "^8.2", + "codeigniter4/framework": "^4.7" + }, + "require-dev": { + "fakerphp/faker": "^1.9", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^10.5.16" + }, + "autoload": { + "psr-4": { + "App\\": "app/", + "Config\\": "app/Config/" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "autoload-dev": { + "psr-4": { + "Tests\\Support\\": "tests/_support" + } + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + }, + "scripts": { + "test": "phpunit" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..9c4ddb2 --- /dev/null +++ b/composer.lock @@ -0,0 +1,2114 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f5cce40800fa5dae1504b9364f585e6a", + "packages": [ + { + "name": "codeigniter4/framework", + "version": "v4.7.0", + "source": { + "type": "git", + "url": "https://github.com/codeigniter4/framework.git", + "reference": "e7753bc03f8b74af428f46b5e2bb74925487c930" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codeigniter4/framework/zipball/e7753bc03f8b74af428f46b5e2bb74925487c930", + "reference": "e7753bc03f8b74af428f46b5e2bb74925487c930", + "shasum": "" + }, + "require": { + "ext-intl": "*", + "ext-mbstring": "*", + "laminas/laminas-escaper": "^2.18", + "php": "^8.2", + "psr/log": "^3.0" + }, + "require-dev": { + "codeigniter/coding-standard": "^1.7", + "fakerphp/faker": "^1.24", + "friendsofphp/php-cs-fixer": "^3.47.1", + "kint-php/kint": "^6.1", + "mikey179/vfsstream": "^1.6.12", + "nexusphp/cs-config": "^3.6", + "phpunit/phpunit": "^10.5.16 || ^11.2", + "predis/predis": "^3.0" + }, + "suggest": { + "ext-apcu": "If you use Cache class ApcuHandler", + "ext-curl": "If you use CURLRequest class", + "ext-dom": "If you use TestResponse", + "ext-exif": "If you run Image class tests", + "ext-fileinfo": "Improves mime type detection for files", + "ext-gd": "If you use Image class GDHandler", + "ext-imagick": "If you use Image class ImageMagickHandler", + "ext-libxml": "If you use TestResponse", + "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", + "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", + "ext-mysqli": "If you use MySQL", + "ext-oci8": "If you use Oracle Database", + "ext-pcntl": "If you use Signals", + "ext-pgsql": "If you use PostgreSQL", + "ext-posix": "If you use Signals", + "ext-readline": "Improves CLI::input() usability", + "ext-redis": "If you use Cache class RedisHandler", + "ext-simplexml": "If you format XML", + "ext-sodium": "If you use Encryption SodiumHandler", + "ext-sqlite3": "If you use SQLite3", + "ext-sqlsrv": "If you use SQL Server", + "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()" + }, + "type": "project", + "autoload": { + "psr-4": { + "CodeIgniter\\": "system/" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The CodeIgniter framework v4", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "slack": "https://codeigniterchat.slack.com", + "source": "https://github.com/codeigniter4/CodeIgniter4" + }, + "time": "2026-02-01T20:39:35+00:00" + }, + { + "name": "laminas/laminas-escaper", + "version": "2.18.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-escaper.git", + "reference": "06f211dfffff18d91844c1f55250d5d13c007e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/06f211dfffff18d91844c1f55250d5d13c007e18", + "reference": "06f211dfffff18d91844c1f55250d5d13c007e18", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-mbstring": "*", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + }, + "conflict": { + "zendframework/zend-escaper": "*" + }, + "require-dev": { + "infection/infection": "^0.31.0", + "laminas/laminas-coding-standard": "~3.1.0", + "phpunit/phpunit": "^11.5.42", + "psalm/plugin-phpunit": "^0.19.5", + "vimeo/psalm": "^6.13.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Laminas\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", + "homepage": "https://laminas.dev", + "keywords": [ + "escaper", + "laminas" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-escaper/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-escaper/issues", + "rss": "https://github.com/laminas/laminas-escaper/releases.atom", + "source": "https://github.com/laminas/laminas-escaper" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2025-10-14T18:31:13+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "mikey179/vfsstream", + "version": "v1.6.12", + "source": { + "type": "git", + "url": "https://github.com/bovigo/vfsStream.git", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" + } + ], + "description": "Virtual file system to mock the real file system in unit tests.", + "homepage": "http://vfs.bovigo.org/", + "support": { + "issues": "https://github.com/bovigo/vfsStream/issues", + "source": "https://github.com/bovigo/vfsStream/tree/master", + "wiki": "https://github.com/bovigo/vfsStream/wiki" + }, + "time": "2024-08-29T18:43:31+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:31:57+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.63", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "33198268dad71e926626b618f3ec3966661e4d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90", + "reference": "33198268dad71e926626b618f3ec3966661e4d90", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.5", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.4", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2026-01-27T05:48:37+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:12:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-01-24T09:25:16+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:37:17+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:15:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-23T08:47:14+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "0735b90f4da94969541dac1da743446e276defa6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", + "reference": "0735b90f4da94969541dac1da743446e276defa6", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:09:11+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:19:19+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:38:20+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-10T07:50:56+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-11-17T20:03:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/env b/env new file mode 100644 index 0000000..f359ec2 --- /dev/null +++ b/env @@ -0,0 +1,69 @@ +#-------------------------------------------------------------------- +# Example Environment Configuration file +# +# This file can be used as a starting point for your own +# custom .env files, and contains most of the possible settings +# available in a default install. +# +# By default, all of the settings are commented out. If you want +# to override the setting, you must un-comment it by removing the '#' +# at the beginning of the line. +#-------------------------------------------------------------------- + +#-------------------------------------------------------------------- +# ENVIRONMENT +#-------------------------------------------------------------------- + +# CI_ENVIRONMENT = production + +#-------------------------------------------------------------------- +# APP +#-------------------------------------------------------------------- + +# app.baseURL = '' +# If you have trouble with `.`, you could also use `_`. +# app_baseURL = '' +# app.forceGlobalSecureRequests = false +# app.CSPEnabled = false + +#-------------------------------------------------------------------- +# DATABASE +#-------------------------------------------------------------------- + +# database.default.hostname = localhost +# database.default.database = ci4 +# database.default.username = root +# database.default.password = root +# database.default.DBDriver = MySQLi +# database.default.DBPrefix = +# database.default.port = 3306 + +# If you use MySQLi as tests, first update the values of Config\Database::$tests. +# database.tests.hostname = localhost +# database.tests.database = ci4_test +# database.tests.username = root +# database.tests.password = root +# database.tests.DBDriver = MySQLi +# database.tests.DBPrefix = +# database.tests.charset = utf8mb4 +# database.tests.DBCollat = utf8mb4_general_ci +# database.tests.port = 3306 + +#-------------------------------------------------------------------- +# ENCRYPTION +#-------------------------------------------------------------------- + +# encryption.key = + +#-------------------------------------------------------------------- +# SESSION +#-------------------------------------------------------------------- + +# session.driver = 'CodeIgniter\Session\Handlers\FileHandler' +# session.savePath = null + +#-------------------------------------------------------------------- +# LOGGER +#-------------------------------------------------------------------- + +# logger.threshold = 4 diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..b408a99 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,63 @@ + + + + + + + + + + + + + ./tests + + + + + + + + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + + + + + + + + + + + + + + diff --git a/preload.php b/preload.php new file mode 100644 index 0000000..288b30b --- /dev/null +++ b/preload.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use CodeIgniter\Boot; +use Config\Paths; + +/* + *--------------------------------------------------------------- + * Sample file for Preloading + *--------------------------------------------------------------- + * See https://www.php.net/manual/en/opcache.preloading.php + * + * How to Use: + * 0. Copy this file to your project root folder. + * 1. Set the $paths property of the preload class below. + * 2. Set opcache.preload in php.ini. + * php.ini: + * opcache.preload=/path/to/preload.php + */ + +// Load the paths config file +require __DIR__ . '/app/Config/Paths.php'; + +// Path to the front controller +define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); + +class preload +{ + /** + * @var array Paths to preload. + */ + private array $paths = [ + [ + 'include' => __DIR__ . '/vendor/codeigniter4/framework/system', // Change this path if using manual installation + 'exclude' => [ + // Not needed if you don't use them. + '/system/Database/OCI8/', + '/system/Database/Postgre/', + '/system/Database/SQLite3/', + '/system/Database/SQLSRV/', + // Not needed for web apps. + '/system/Database/Seeder.php', + '/system/Test/', + '/system/CLI/', + '/system/Commands/', + '/system/Publisher/', + '/system/ComposerScripts.php', + // Not Class/Function files. + '/system/Config/Routes.php', + '/system/Language/', + '/system/bootstrap.php', + '/system/util_bootstrap.php', + '/system/rewrite.php', + '/Views/', + // Errors occur. + '/system/ThirdParty/', + ], + ], + ]; + + public function __construct() + { + $this->loadAutoloader(); + } + + private function loadAutoloader(): void + { + $paths = new Paths(); + require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'Boot.php'; + + Boot::preload($paths); + } + + /** + * Load PHP files. + */ + public function load(): void + { + foreach ($this->paths as $path) { + $directory = new RecursiveDirectoryIterator($path['include']); + $fullTree = new RecursiveIteratorIterator($directory); + $phpFiles = new RegexIterator( + $fullTree, + '/.+((? $file) { + foreach ($path['exclude'] as $exclude) { + if (str_contains($file[0], $exclude)) { + continue 2; + } + } + + require_once $file[0]; + // Uncomment only for debugging (to inspect which files are included). + // Never use this in production - preload scripts must not generate output. + // echo 'Loaded: ' . $file[0] . "\n"; + } + } + } +} + +(new preload())->load(); diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..abac3cb --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,49 @@ +# Disable directory browsing +Options -Indexes + +# ---------------------------------------------------------------------- +# Rewrite engine +# ---------------------------------------------------------------------- + +# Turning on the rewrite engine is necessary for the following rules and features. +# FollowSymLinks must be enabled for this to work. + + Options +FollowSymlinks + RewriteEngine On + + # If you installed CodeIgniter in a subfolder, you will need to + # change the following line to match the subfolder you need. + # http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase + # RewriteBase / + + # Redirect Trailing Slashes... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Rewrite "www.example.com -> example.com" + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + # Checks to see if the user is attempting to access a valid file, + # such as an image or css document, if this isn't true it sends the + # request to the front controller, index.php + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^([\s\S]*)$ index.php/$1 [L,NC,QSA] + + # Ensure Authorization header is passed along + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + + + # If we don't have mod_rewrite installed, all 404's + # can be sent to index.php, and everything works as normal. + ErrorDocument 404 index.php + + +# Disable server signature start +ServerSignature Off +# Disable server signature end diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..7ecfce2 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..16b64c1 --- /dev/null +++ b/public/index.php @@ -0,0 +1,80 @@ +systemDirectory . '/Boot.php'; + +exit(Boot::bootWeb($paths)); diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..9e60f97 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/spark b/spark new file mode 100755 index 0000000..61bc572 --- /dev/null +++ b/spark @@ -0,0 +1,87 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use CodeIgniter\Boot; +use Config\Paths; + +/* + * -------------------------------------------------------------------- + * CODEIGNITER COMMAND-LINE TOOLS + * -------------------------------------------------------------------- + * The main entry point into the CLI system and allows you to run + * commands and perform maintenance on your application. + */ + +/* + *--------------------------------------------------------------- + * CHECK SERVER API + *--------------------------------------------------------------- + */ + +// Refuse to run when called from php-cgi +if (str_starts_with(PHP_SAPI, 'cgi')) { + exit("The cli tool is not supported when running php-cgi. It needs php-cli to function!\n\n"); +} + +/* + *--------------------------------------------------------------- + * CHECK PHP VERSION + *--------------------------------------------------------------- + */ + +$minPhpVersion = '8.2'; // If you update this, don't forget to update `public/index.php`. +if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { + $message = sprintf( + 'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s', + $minPhpVersion, + PHP_VERSION, + ); + + exit($message); +} + +// We want errors to be shown when using it from the CLI. +error_reporting(E_ALL); +ini_set('display_errors', '1'); + +/* + *--------------------------------------------------------------- + * SET THE CURRENT DIRECTORY + *--------------------------------------------------------------- + */ + +// Path to the front controller +define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); + +// Ensure the current directory is pointing to the front controller's directory +chdir(FCPATH); + +/* + *--------------------------------------------------------------- + * BOOTSTRAP THE APPLICATION + *--------------------------------------------------------------- + * This process sets up the path constants, loads and registers + * our autoloader, along with Composer's, loads our constants + * and fires up an environment-specific bootstrapping. + */ + +// LOAD OUR PATHS CONFIG FILE +// This is the line that might need to be changed, depending on your folder structure. +require FCPATH . '../app/Config/Paths.php'; +// ^^^ Change this line if you move your application folder + +$paths = new Paths(); + +// LOAD THE FRAMEWORK BOOTSTRAP FILE +require $paths->systemDirectory . '/Boot.php'; + +exit(Boot::bootSpark($paths)); diff --git a/tests/.htaccess b/tests/.htaccess new file mode 100644 index 0000000..3462048 --- /dev/null +++ b/tests/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..fc40e44 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,118 @@ +# Running Application Tests + +This is the quick-start to CodeIgniter testing. Its intent is to describe what +it takes to set up your application and get it ready to run unit tests. +It is not intended to be a full description of the test features that you can +use to test your application. Those details can be found in the documentation. + +## Resources + +* [CodeIgniter 4 User Guide on Testing](https://codeigniter.com/user_guide/testing/index.html) +* [PHPUnit docs](https://phpunit.de/documentation.html) +* [Any tutorials on Unit testing in CI4?](https://forum.codeigniter.com/showthread.php?tid=81830) + +## Requirements + +It is recommended to use the latest version of PHPUnit. At the time of this +writing, we are running version 9.x. Support for this has been built into the +**composer.json** file that ships with CodeIgniter and can easily be installed +via [Composer](https://getcomposer.org/) if you don't already have it installed globally. + +```console +> composer install +``` + +If running under macOS or Linux, you can create a symbolic link to make running tests a touch nicer. + +```console +> ln -s ./vendor/bin/phpunit ./phpunit +``` + +You also need to install [XDebug](https://xdebug.org/docs/install) in order +for code coverage to be calculated successfully. After installing `XDebug`, you must add `xdebug.mode=coverage` in the **php.ini** file to enable code coverage. + +## Setting Up + +A number of the tests use a running database. +In order to set up the database edit the details for the `tests` group in +**app/Config/Database.php** or **.env**. +Make sure that you provide a database engine that is currently running on your machine. +More details on a test database setup are in the +[Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) section of the documentation. + +## Running the tests + +The entire test suite can be run by simply typing one command-line command from the main directory. + +```console +> ./phpunit +``` + +If you are using Windows, use the following command. + +```console +> vendor\bin\phpunit +``` + +You can limit tests to those within a single test directory by specifying the +directory name after phpunit. + +```console +> ./phpunit app/Models +``` + +## Generating Code Coverage + +To generate coverage information, including HTML reports you can view in your browser, +you can use the following command: + +```console +> ./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m +``` + +This runs all of the tests again collecting information about how many lines, +functions, and files are tested. It also reports the percentage of the code that is covered by tests. +It is collected in two formats: a simple text file that provides an overview as well +as a comprehensive collection of HTML files that show the status of every line of code in the project. + +The text file can be found at **tests/coverage.txt**. +The HTML files can be viewed by opening **tests/coverage/index.html** in your favorite browser. + +## PHPUnit XML Configuration + +The repository has a ``phpunit.xml.dist`` file in the project root that's used for +PHPUnit configuration. This is used to provide a default configuration if you +do not have your own configuration file in the project root. + +The normal practice would be to copy ``phpunit.xml.dist`` to ``phpunit.xml`` +(which is git ignored), and to tailor it as you see fit. +For instance, you might wish to exclude database tests, or automatically generate +HTML code coverage reports. + +## Test Cases + +Every test needs a *test case*, or class that your tests extend. CodeIgniter 4 +provides one class that you may use directly: +* `CodeIgniter\Test\CIUnitTestCase` + +Most of the time you will want to write your own test cases that extend `CIUnitTestCase` +to hold functions and services common to your test suites. + +## Creating Tests + +All tests go in the **tests/** directory. Each test file is a class that extends a +**Test Case** (see above) and contains methods for the individual tests. These method +names must start with the word "test" and should have descriptive names for precisely what +they are testing: +`testUserCanModifyFile()` `testOutputColorMatchesInput()` `testIsLoggedInFailsWithInvalidUser()` + +Writing tests is an art, and there are many resources available to help learn how. +Review the links above and always pay attention to your code coverage. + +### Database Tests + +Tests can include migrating, seeding, and testing against a mock or live database. +Be sure to modify the test case (or create your own) to point to your seed and migrations +and include any additional steps to be run before tests in the `setUp()` method. +See [Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) +for details. diff --git a/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php new file mode 100644 index 0000000..a73356d --- /dev/null +++ b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -0,0 +1,37 @@ +forge->addField('id'); + $this->forge->addField([ + 'name' => ['type' => 'varchar', 'constraint' => 31], + 'uid' => ['type' => 'varchar', 'constraint' => 31], + 'class' => ['type' => 'varchar', 'constraint' => 63], + 'icon' => ['type' => 'varchar', 'constraint' => 31], + 'summary' => ['type' => 'varchar', 'constraint' => 255], + 'created_at' => ['type' => 'datetime', 'null' => true], + 'updated_at' => ['type' => 'datetime', 'null' => true], + 'deleted_at' => ['type' => 'datetime', 'null' => true], + ]); + + $this->forge->addKey('name'); + $this->forge->addKey('uid'); + $this->forge->addKey(['deleted_at', 'id']); + $this->forge->addKey('created_at'); + + $this->forge->createTable('factories'); + } + + public function down(): void + { + $this->forge->dropTable('factories'); + } +} diff --git a/tests/_support/Database/Seeds/ExampleSeeder.php b/tests/_support/Database/Seeds/ExampleSeeder.php new file mode 100644 index 0000000..619fc27 --- /dev/null +++ b/tests/_support/Database/Seeds/ExampleSeeder.php @@ -0,0 +1,41 @@ + 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Longer sample text for testing', + ], + [ + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Create widgets in your factory', + ], + [ + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', + 'summary' => 'Abandon all hope, ye who enter here', + ], + ]; + + $builder = $this->db->table('factories'); + + foreach ($factories as $factory) { + $builder->insert($factory); + } + } +} diff --git a/tests/_support/Libraries/ConfigReader.php b/tests/_support/Libraries/ConfigReader.php new file mode 100644 index 0000000..0bb4a8f --- /dev/null +++ b/tests/_support/Libraries/ConfigReader.php @@ -0,0 +1,19 @@ +findAll(); + + // Make sure the count is as expected + $this->assertCount(3, $objects); + } + + public function testSoftDeleteLeavesRow(): void + { + $model = new ExampleModel(); + $this->setPrivateProperty($model, 'useSoftDeletes', true); + $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); + + /** @var stdClass $object */ + $object = $model->first(); + $model->delete($object->id); + + // The model should no longer find it + $this->assertNull($model->find($object->id)); + + // ... but it should still be in the database + $result = $model->builder()->where('id', $object->id)->get()->getResult(); + + $this->assertCount(1, $result); + } +} diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/tests/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/tests/session/ExampleSessionTest.php b/tests/session/ExampleSessionTest.php new file mode 100644 index 0000000..33242a4 --- /dev/null +++ b/tests/session/ExampleSessionTest.php @@ -0,0 +1,17 @@ +set('logged_in', 123); + $this->assertSame(123, $session->get('logged_in')); + } +} diff --git a/tests/unit/HealthTest.php b/tests/unit/HealthTest.php new file mode 100644 index 0000000..b3e480f --- /dev/null +++ b/tests/unit/HealthTest.php @@ -0,0 +1,49 @@ +assertTrue(defined('APPPATH')); + } + + public function testBaseUrlHasBeenSet(): void + { + $validation = service('validation'); + + $env = false; + + // Check the baseURL in .env + if (is_file(HOMEPATH . '.env')) { + $env = preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')) !== false; + } + + if ($env) { + // BaseURL in .env is a valid URL? + // phpunit.xml.dist sets app.baseURL in $_SERVER + // So if you set app.baseURL in .env, it takes precedence + $config = new App(); + $this->assertTrue( + $validation->check($config->baseURL, 'valid_url'), + 'baseURL "' . $config->baseURL . '" in .env is not valid URL', + ); + } + + // Get the baseURL in app/Config/App.php + // You can't use Config\App, because phpunit.xml.dist sets app.baseURL + $reader = new ConfigReader(); + + // BaseURL in app/Config/App.php is a valid URL? + $this->assertTrue( + $validation->check($reader->baseURL, 'valid_url'), + 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL', + ); + } +} diff --git a/writable/.htaccess b/writable/.htaccess new file mode 100755 index 0000000..3462048 --- /dev/null +++ b/writable/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/writable/cache/index.html b/writable/cache/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/cache/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/database/code_master_init_daegu.sql b/writable/database/code_master_init_daegu.sql new file mode 100644 index 0000000..0f877e2 --- /dev/null +++ b/writable/database/code_master_init_daegu.sql @@ -0,0 +1,371 @@ +-- 대구광역시(특히 북구) 기준 기본코드 초기 데이터 스크립트 +-- 실행 순서: +-- 1) code_kind / code_detail 테이블 생성 +-- 2) code_kind 데이터 입력 +-- 3) code_detail 데이터 입력 + +/* ========================================================= + * 1. 테이블 생성 (이미 존재하면 생략 가능) + * =======================================================*/ + +CREATE TABLE IF NOT EXISTS `code_kind` ( + `ck_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '코드종류 PK', + `ck_code` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '종류 코드(A~Y 등)', + `ck_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '종류 명칭', + `ck_state` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=사용, 0=미사용', + `ck_regdate` DATETIME NOT NULL COMMENT '등록일시', + PRIMARY KEY (`ck_idx`), + UNIQUE KEY `uk_ck_code` (`ck_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='기본코드 종류'; + +CREATE TABLE IF NOT EXISTS `code_detail` ( + `cd_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '세부코드 PK', + `cd_ck_idx` INT UNSIGNED NOT NULL COMMENT 'code_kind FK', + `cd_code` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '세부 코드', + `cd_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '세부 명칭', + `cd_sort` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '정렬 순서', + `cd_state` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=사용, 0=미사용', + `cd_regdate` DATETIME NOT NULL COMMENT '등록일시', + PRIMARY KEY (`cd_idx`), + KEY `idx_cd_ck_idx` (`cd_ck_idx`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='세부 기본코드'; + + +/* ========================================================= + * 2. code_kind 초기 데이터 + * (중복 실행 시 uk_ck_code 제약 때문에 에러 가능) + * =======================================================*/ + +INSERT INTO `code_kind` (`ck_code`, `ck_name`, `ck_state`, `ck_regdate`) VALUES + ('A', '도/특별시/광역시 구분', 1, NOW()), + ('B', '특별시/광역시/시/군 코드', 1, NOW()), + ('C', '구 코드', 1, NOW()), + ('D', '동 코드', 1, NOW()), + ('E', '봉투구분', 1, NOW()), + ('F', '봉투재질', 1, NOW()), + ('G', '용량별', 1, NOW()), + ('H', '무상지급 구분', 1, NOW()), + ('I', '판매형태', 1, NOW()), + ('J', '반품형태', 1, NOW()), + ('K', '반품사유', 1, NOW()), + ('L', '지정판매소 변경사유', 1, NOW()), + ('M', '수불구분', 1, NOW()), + ('N', '동판종류', 1, NOW()), + ('O', '봉투명', 1, NOW()), + ('P', '작업권한', 1, NOW()), + ('Q', '예산과목', 1, NOW()), + ('R', '은행목록', 1, NOW()), + ('S', '소속', 1, NOW()), + ('T', '직위', 1, NOW()); + + +/* ========================================================= + * 3. code_detail 초기 데이터 + * 3-1. 행정구역 관련 (대구광역시, 북구 및 북구 동) + * =======================================================*/ + +-- A: 도/특별시/광역시 구분 – 대구는 광역시만 사용 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, '11', '광역시', 10, 1, NOW() +FROM code_kind WHERE ck_code = 'A'; + +-- B: 특별시/광역시/시/군 코드 – 대구광역시 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, '1102', '대구광역시', 10, 1, NOW() +FROM code_kind WHERE ck_code = 'B'; + +-- C: 구코드 – 북구 (CSV: 110209, 북구) +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, '110209', '북구', 10, 1, NOW() +FROM code_kind WHERE ck_code = 'C'; + +-- D: 동코드 – 대구 북구의 동들 (11020901~11020928) +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '11020901' AS cd_code, '검단동' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '11020902', '고성동1가', 20 UNION ALL + SELECT '11020903', '고성동2가', 30 UNION ALL + SELECT '11020904', '고성동3가', 40 UNION ALL + SELECT '11020905', '관음동', 50 UNION ALL + SELECT '11020906', '구암동', 60 UNION ALL + SELECT '11020907', '국우동', 70 UNION ALL + SELECT '11020908', '금호동', 80 UNION ALL + SELECT '11020909', '노곡동', 90 UNION ALL + SELECT '11020910', '노원동1가', 100 UNION ALL + SELECT '11020911', '노원동2가', 110 UNION ALL + SELECT '11020912', '노원동3가', 120 UNION ALL + SELECT '11020913', '대현동', 130 UNION ALL + SELECT '11020914', '도남동', 140 UNION ALL + SELECT '11020915', '동변동', 150 UNION ALL + SELECT '11020916', '동천동', 160 UNION ALL + SELECT '11020917', '동호동', 170 UNION ALL + SELECT '11020918', '매천동', 180 UNION ALL + SELECT '11020919', '복현동', 190 UNION ALL + SELECT '11020920', '사수동', 200 UNION ALL + SELECT '11020921', '산격동', 210 UNION ALL + SELECT '11020922', '서변동', 220 UNION ALL + SELECT '11020923', '연경동', 230 UNION ALL + SELECT '11020924', '읍내동', 240 UNION ALL + SELECT '11020925', '조야동', 250 UNION ALL + SELECT '11020926', '칠성동1가', 260 UNION ALL + SELECT '11020927', '칠성동2가', 270 UNION ALL + SELECT '11020928', '침산동', 280 +) AS v +ON code_kind.ck_code = 'D'; + + +/* ========================================================= + * 3-2. 봉투·재질·용량·무상·판매형태 (E~I) + * =======================================================*/ + +-- E: 봉투구분 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '10' AS cd_code, '일반용' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '20' AS cd_code, '공공용' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '30' AS cd_code, '무료용' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '40' AS cd_code, '공동주택용' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '50' AS cd_code, '재사용' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '60' AS cd_code, '음식물 봉투' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '61' AS cd_code, '음식물 스티커' AS cd_name, 70 AS cd_sort UNION ALL + SELECT '62' AS cd_code, '음식물 용기' AS cd_name, 80 AS cd_sort UNION ALL + SELECT '70' AS cd_code, '대형폐기물 스티커' AS cd_name, 90 AS cd_sort +) AS v +ON code_kind.ck_code = 'E'; + +-- F: 봉투재질 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '2' AS cd_code, '고밀도' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '6' AS cd_code, 'PP마대' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '7' AS cd_code, '스티커' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '8' AS cd_code, '용기' AS cd_name, 40 AS cd_sort +) AS v +ON code_kind.ck_code = 'F'; + +-- G: 용량별 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '10' AS cd_code, '2L' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '11' AS cd_code, '3L' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '12' AS cd_code, '5L' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '13' AS cd_code, '10L' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '15' AS cd_code, '20L' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '16' AS cd_code, '30L' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '17' AS cd_code, '50L' AS cd_name, 70 AS cd_sort UNION ALL + SELECT '18' AS cd_code, '60L' AS cd_name, 80 AS cd_sort UNION ALL + SELECT '19' AS cd_code, '75L' AS cd_name, 90 AS cd_sort UNION ALL + SELECT '20' AS cd_code, '100L' AS cd_name, 100 AS cd_sort UNION ALL + SELECT '21' AS cd_code, '120L' AS cd_name, 110 AS cd_sort +) AS v +ON code_kind.ck_code = 'G'; + +-- H: 무상지급 구분 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '시설보호대상자' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '10' AS cd_code, '생보자' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '3' AS cd_code, '대한민국무공수훈자' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '4' AS cd_code, '사회복지시설' AS cd_name, 40 AS cd_sort +) AS v +ON code_kind.ck_code = 'H'; + +-- I: 판매형태 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '무상지급' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '일반판매' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '3' AS cd_code, '관내판매' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '4' AS cd_code, '교환판매' AS cd_name, 40 AS cd_sort +) AS v +ON code_kind.ck_code = 'I'; + + +/* ========================================================= + * 3-3. 반품·수불·동판·봉투명·작업권한·예산·은행 (J~R) + * =======================================================*/ + +-- J: 반품형태 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '일반반품' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '관내반품' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '3' AS cd_code, '반품' AS cd_name, 30 AS cd_sort +) AS v +ON code_kind.ck_code = 'J'; + +-- K: 반품사유 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '봉투훼손' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '지정판매소 폐업' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '4' AS cd_code, '스티커 미사용' AS cd_name, 30 AS cd_sort +) AS v +ON code_kind.ck_code = 'K'; + +-- L: 지정판매소 변경사유 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '지정판매소변경사유1' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '지정판매소변경사유2' AS cd_name, 20 AS cd_sort +) AS v +ON code_kind.ck_code = 'L'; + +-- M: 수불구분 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '10' AS cd_code, '실사입고' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '11' AS cd_code, '신청입고' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '12' AS cd_code, '무료입고' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '13' AS cd_code, '발주입고' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '16' AS cd_code, '반품입고(정상)' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '17' AS cd_code, '반품입고(불용)' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '18' AS cd_code, '이동입고' AS cd_name, 70 AS cd_sort UNION ALL + SELECT '1A' AS cd_code, '교환입고' AS cd_name, 80 AS cd_sort UNION ALL + SELECT '1B' AS cd_code, '기타입고' AS cd_name, 90 AS cd_sort UNION ALL + SELECT '20' AS cd_code, '실사출고' AS cd_name, 100 AS cd_sort UNION ALL + SELECT '21' AS cd_code, '신청불출' AS cd_name, 110 AS cd_sort UNION ALL + SELECT '22' AS cd_code, '무료불출' AS cd_name, 120 AS cd_sort UNION ALL + SELECT '23' AS cd_code, '일반판매' AS cd_name, 130 AS cd_sort UNION ALL + SELECT '24' AS cd_code, '공공출고' AS cd_name, 140 AS cd_sort UNION ALL + SELECT '26' AS cd_code, '반품출고(정상)' AS cd_name, 150 AS cd_sort UNION ALL + SELECT '27' AS cd_code, '반품출고(불용)' AS cd_name, 160 AS cd_sort UNION ALL + SELECT '28' AS cd_code, '이동출고' AS cd_name, 170 AS cd_sort UNION ALL + SELECT '29' AS cd_code, '파기처리' AS cd_name, 180 AS cd_sort UNION ALL + SELECT '2A' AS cd_code, '교환출고' AS cd_name, 190 AS cd_sort UNION ALL + SELECT '2B' AS cd_code, '기타출고' AS cd_name, 200 AS cd_sort UNION ALL + SELECT '99' AS cd_code, '시찰' AS cd_name, 210 AS cd_sort +) AS v +ON code_kind.ck_code = 'M'; + +-- N: 동판종류 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '10' AS cd_code, '동판 종류1' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '20' AS cd_code, '동판 종류2' AS cd_name, 20 AS cd_sort +) AS v +ON code_kind.ck_code = 'N'; + +-- O: 봉투명 (상세 봉투 코드) +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '10112' AS cd_code, '일반용 3L' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '10122' AS cd_code, '일반용 5L' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '10132' AS cd_code, '일반용 10L' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '10152' AS cd_code, '일반용 20L' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '10162' AS cd_code, '일반용 30L' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '10172' AS cd_code, '일반용 50L' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '10192' AS cd_code, '일반용 75L' AS cd_name, 70 AS cd_sort UNION ALL + SELECT '10202' AS cd_code, '일반용 100L' AS cd_name, 80 AS cd_sort UNION ALL + SELECT '20172' AS cd_code, '공공용 50L' AS cd_name, 90 AS cd_sort UNION ALL + SELECT '40152' AS cd_code, '공동주택용 20L' AS cd_name, 100 AS cd_sort UNION ALL + SELECT '40182' AS cd_code, '공동주택용 60L' AS cd_name, 110 AS cd_sort UNION ALL + SELECT '40212' AS cd_code, '공동주택용 120L' AS cd_name, 120 AS cd_sort UNION ALL + SELECT '50122' AS cd_code, '재사용 5L' AS cd_name, 130 AS cd_sort UNION ALL + SELECT '60102' AS cd_code, '음식물 2L' AS cd_name, 140 AS cd_sort UNION ALL + SELECT '60132' AS cd_code, '음식물 10L' AS cd_name, 150 AS cd_sort UNION ALL + SELECT '61107' AS cd_code, '음식물 스티커 2L' AS cd_name, 160 AS cd_sort UNION ALL + SELECT '61117' AS cd_code, '음식물 스티커 3L' AS cd_name, 170 AS cd_sort UNION ALL + SELECT '61127' AS cd_code, '음식물 스티커 5L' AS cd_name, 180 AS cd_sort UNION ALL + SELECT '61157' AS cd_code, '음식물 스티커 20L' AS cd_name, 190 AS cd_sort UNION ALL + SELECT '61187' AS cd_code, '음식물 스티커 60L' AS cd_name, 200 AS cd_sort UNION ALL + SELECT '61217' AS cd_code, '음식물 스티커 120L' AS cd_name, 210 AS cd_sort UNION ALL + SELECT '62128' AS cd_code, '음식물용기 5L' AS cd_name, 220 AS cd_sort UNION ALL + SELECT '62158' AS cd_code, '음식물용기 20L' AS cd_name, 230 AS cd_sort UNION ALL + SELECT '70707' AS cd_code, '폐기물 스티커 1,000원' AS cd_name, 240 AS cd_sort UNION ALL + SELECT '70727' AS cd_code, '폐기물 스티커 3,000원' AS cd_name, 250 AS cd_sort UNION ALL + SELECT '70747' AS cd_code, '폐기물 스티커 5,000원' AS cd_name, 260 AS cd_sort UNION ALL + SELECT '70787' AS cd_code, '폐기물 스티커 10,000원'AS cd_name, 270 AS cd_sort +) AS v +ON code_kind.ck_code = 'O'; + +-- P: 작업권한 (예시 – 실제 운영 정책에 맞게 확장 가능) +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, '111', '등록-다시', 10, 1, NOW() +FROM code_kind WHERE ck_code = 'P'; + +-- Q: 예산과목 (대표 코드만 선행 입력) +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1000' AS cd_code, '관' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '1001' AS cd_code, '보건및생활환경개선비' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '2000' AS cd_code, '항' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '2010' AS cd_code, '환경관리' AS cd_name, 40 AS cd_sort +) AS v +ON code_kind.ck_code = 'Q'; + +-- R: 은행목록 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '4' AS cd_code, '국민은행' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '7' AS cd_code, '수협' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '20' AS cd_code, '우리은행' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '32' AS cd_code, '부산은행' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '99' AS cd_code, '새마을금고' AS cd_name, 50 AS cd_sort +) AS v +ON code_kind.ck_code = 'R'; + + +/* ========================================================= + * 3-4. 소속(S), 직위(T) + * =======================================================*/ + +-- S: 소속 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '청소과' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '청소행정과' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '3' AS cd_code, '자원순환과' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '4' AS cd_code, '도시미화과' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '5' AS cd_code, '영업부' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '6' AS cd_code, '관리부' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '7' AS cd_code, '기술부' AS cd_name, 70 AS cd_sort +) AS v +ON code_kind.ck_code = 'S'; + +-- T: 직위 +INSERT INTO `code_detail` (`cd_ck_idx`, `cd_code`, `cd_name`, `cd_sort`, `cd_state`, `cd_regdate`) +SELECT ck_idx, v.cd_code, v.cd_name, v.cd_sort, 1, NOW() +FROM code_kind +JOIN ( + SELECT '1' AS cd_code, '7급' AS cd_name, 10 AS cd_sort UNION ALL + SELECT '2' AS cd_code, '8급' AS cd_name, 20 AS cd_sort UNION ALL + SELECT '3' AS cd_code, '9급' AS cd_name, 30 AS cd_sort UNION ALL + SELECT '4' AS cd_code, '기능' AS cd_name, 40 AS cd_sort UNION ALL + SELECT '5' AS cd_code, '계장' AS cd_name, 50 AS cd_sort UNION ALL + SELECT '6' AS cd_code, '과장' AS cd_name, 60 AS cd_sort UNION ALL + SELECT '7' AS cd_code, '사장' AS cd_name, 70 AS cd_sort UNION ALL + SELECT '8' AS cd_code, '상무' AS cd_name, 80 AS cd_sort +) AS v +ON code_kind.ck_code = 'T'; + diff --git a/writable/database/init_jongryangje_dev.sql b/writable/database/init_jongryangje_dev.sql new file mode 100644 index 0000000..fbbe410 --- /dev/null +++ b/writable/database/init_jongryangje_dev.sql @@ -0,0 +1,15 @@ +-- 종량제 로컬 개발 DB 초기화 +-- 실행: mariadb -u root < writable/database/init_jongryangje_dev.sql +-- 또는: mysql -u root < writable/database/init_jongryangje_dev.sql + +CREATE DATABASE IF NOT EXISTS jongryangje_dev + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +CREATE USER IF NOT EXISTS 'jongryangje'@'localhost' + IDENTIFIED BY 'jongryangje_dev'; + +GRANT ALL PRIVILEGES ON jongryangje_dev.* TO 'jongryangje'@'localhost'; +FLUSH PRIVILEGES; + +SELECT 'jongryangje_dev DB and user ready.' AS result; diff --git a/writable/database/local_government_init_daegu.sql b/writable/database/local_government_init_daegu.sql new file mode 100644 index 0000000..17c962f --- /dev/null +++ b/writable/database/local_government_init_daegu.sql @@ -0,0 +1,21 @@ +-- 대구광역시 전체 구·군 지자체 초기 데이터 +-- 코드 설계: 코드 B(1102) = 대구광역시, 코드 C = 1102 + 구 순번 2자리 (기본코드 종류 CSV 규칙) +-- 실행 전 local_government 테이블이 생성되어 있어야 함. +-- 중복 실행 시 uk_lg_code 제약으로 인해 에러 가능 → 기존 데이터 삭제 후 실행하거나, INSERT IGNORE 사용 + +/* ========================================================= + * 지자체 코드 (lg_code) 규칙 + * - 110201 ~ 110209: 대구광역시 구·군 (1102 + 순번 01~09, 08 제외) + * - 110201 중구, 110202 동구, 110203 서구, 110204 남구, + * 110205 수성구, 110206 달서구, 110207 달성군, 110209 북구 + * =======================================================*/ + +INSERT INTO `local_government` (`lg_name`, `lg_code`, `lg_sido`, `lg_gugun`, `lg_addr`, `lg_state`, `lg_regdate`) VALUES +('중구청', '110201', '대구광역시', '중구', '대구광역시 중구 중앙대로 394', 1, NOW()), +('동구청', '110202', '대구광역시', '동구', '대구광역시 동구 동대구로 205', 1, NOW()), +('서구청', '110203', '대구광역시', '서구', '대구광역시 서구 달서로 250', 1, NOW()), +('남구청', '110204', '대구광역시', '남구', '대구광역시 남구 대명로 215', 1, NOW()), +('수성구청', '110205', '대구광역시', '수성구', '대구광역시 수성구 달구벌대로 2450', 1, NOW()), +('달서구청', '110206', '대구광역시', '달서구', '대구광역시 달서구 달서대로 600', 1, NOW()), +('달성군청', '110207', '대구광역시', '달성군', '대구광역시 달성군 화원읍 비슬로 2350', 1, NOW()), +('북구청', '110209', '대구광역시', '북구', '대구광역시 북구 옥산로 65', 1, NOW()); diff --git a/writable/database/login_tables.sql b/writable/database/login_tables.sql new file mode 100644 index 0000000..6af4aa2 --- /dev/null +++ b/writable/database/login_tables.sql @@ -0,0 +1,122 @@ +-- 로그인 기능용 테이블 (docs/11-login-logout-development-guide.md 기준) +-- 실행: mysql -h 127.0.0.1 -P 3306 -u jongryangje -p jongryangje_dev < writable/database/login_tables.sql + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- --------------------------------------------------------------------------- +-- member: 로그인·권한용 회원 테이블 +-- mb_state: 1=정상, 2=정지, 0=탈퇴 +-- mb_level: app/Config/Roles.php 참고 +-- 1=일반 사용자, 2=지정판매소, 3=지자체관리자, 4=super admin +-- --------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `member` ( + `mb_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '회원 PK', + `mb_id` VARCHAR(50) NOT NULL COMMENT '로그인 아이디', + `mb_passwd` VARCHAR(255) NOT NULL COMMENT '비밀번호 해시(password_hash)', + `mb_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '이름', + `mb_email` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '이메일', + `mb_phone` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '연락처', + `mb_lang` VARCHAR(10) NOT NULL DEFAULT 'ko' COMMENT '언어', + `mb_level` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=일반, 2=지정판매소, 3=지자체관리자, 4=super admin (Roles.php)', + `mb_group` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '권한 그룹 코드(Phase 2)', + `mb_lg_idx` INT UNSIGNED NULL DEFAULT NULL COMMENT '소속 지자체 PK(지자체관리자만 사용)', + `mb_state` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=정상, 2=정지, 0=탈퇴', + `mb_regdate` DATETIME NOT NULL COMMENT '가입일시', + `mb_latestdate` DATETIME NULL DEFAULT NULL COMMENT '최근 로그인 일시', + `mb_leavedate` DATETIME NULL DEFAULT NULL COMMENT '탈퇴일시', + PRIMARY KEY (`mb_idx`), + UNIQUE KEY `uk_mb_id` (`mb_id`), + KEY `idx_mb_state` (`mb_state`), + KEY `idx_mb_lg_idx` (`mb_lg_idx`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='회원(로그인·권한)'; + +-- --------------------------------------------------------------------------- +-- member_log: 로그인/로그아웃 이력 전용 +-- --------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `member_log` ( + `mll_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 PK', + `mll_success` TINYINT(1) NOT NULL COMMENT '1=성공, 0=실패', + `mb_idx` INT UNSIGNED NULL DEFAULT NULL COMMENT '회원 PK(실패 시 NULL 가능)', + `mb_id` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '로그인 시도 아이디', + `mll_regdate` DATETIME NOT NULL COMMENT '로그 일시', + `mll_ip` VARCHAR(45) NOT NULL DEFAULT '' COMMENT 'IP', + `mll_msg` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '메시지(실패 사유 등)', + `mll_useragent` VARCHAR(500) NOT NULL DEFAULT '' COMMENT 'User-Agent', + `mll_logout_date` DATETIME NULL DEFAULT NULL COMMENT '로그아웃 일시', + `mll_url` VARCHAR(500) NULL DEFAULT NULL COMMENT '요청 URL(선택)', + `mll_referer` VARCHAR(500) NULL DEFAULT NULL COMMENT 'Referer(선택)', + `mll_country` VARCHAR(10) NULL DEFAULT NULL COMMENT '국가 코드(선택)', + `at_token` VARCHAR(100) NULL DEFAULT NULL COMMENT '세션/토큰 식별(선택)', + PRIMARY KEY (`mll_idx`), + KEY `idx_mll_mb_idx` (`mb_idx`), + KEY `idx_mll_regdate` (`mll_regdate`), + KEY `idx_mll_success` (`mll_success`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='로그인/로그아웃 이력'; + +-- --------------------------------------------------------------------------- +-- member_approval_request: 회원가입 역할 승인 요청 이력 +-- 공개 회원가입 시 생성되며, 승인 후에만 requested_level이 member.mb_level로 반영됨 +-- --------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `member_approval_request` ( + `mar_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '승인요청 PK', + `mb_idx` INT UNSIGNED NOT NULL COMMENT '회원 FK(member.mb_idx)', + `mar_requested_level` TINYINT UNSIGNED NOT NULL COMMENT '요청 역할(1,2,3)', + `mar_status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT 'pending|approved|rejected', + `mar_request_note` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '요청 메모', + `mar_reject_reason` VARCHAR(255) NULL DEFAULT NULL COMMENT '반려 사유', + `mar_requested_at` DATETIME NOT NULL COMMENT '요청일시', + `mar_requested_by` INT UNSIGNED NULL DEFAULT NULL COMMENT '요청자 mb_idx', + `mar_processed_at` DATETIME NULL DEFAULT NULL COMMENT '처리일시', + `mar_processed_by` INT UNSIGNED NULL DEFAULT NULL COMMENT '처리자 mb_idx', + PRIMARY KEY (`mar_idx`), + KEY `idx_mar_mb_idx` (`mb_idx`), + KEY `idx_mar_status_requested` (`mar_status`, `mar_requested_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='회원가입 역할 승인 요청'; + +-- --------------------------------------------------------------------------- +-- local_government: 지자체 마스터 (테넌트 루트) +-- --------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `local_government` ( + `lg_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '지자체 PK', + `lg_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '지자체명(예: OO구청)', + `lg_code` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '지자체/구군 코드(행정코드)', + `lg_sido` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '시/도', + `lg_gugun` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '구/군', + `lg_addr` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '주소', + `lg_state` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=사용, 0=미사용', + `lg_regdate` DATETIME NOT NULL COMMENT '등록일시', + PRIMARY KEY (`lg_idx`), + UNIQUE KEY `uk_lg_code` (`lg_code`), + KEY `idx_lg_state` (`lg_state`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='지자체(테넌트 루트)'; + +-- --------------------------------------------------------------------------- +-- designated_shop: 지정판매소 +-- --------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `designated_shop` ( + `ds_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '지정판매소 PK', + `ds_lg_idx` INT UNSIGNED NOT NULL COMMENT '소속 지자체 FK', + `ds_mb_idx` INT UNSIGNED NULL DEFAULT NULL COMMENT '로그인 회원 FK(1:1)', + `ds_shop_no` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '판매소번호', + `ds_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '상호명', + `ds_biz_no` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '사업자번호', + `ds_rep_name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '대표자명', + `ds_va_number` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '고정 가상계좌 번호', + `ds_zip` VARCHAR(10) NOT NULL DEFAULT '' COMMENT '우편번호', + `ds_addr` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '도로명주소', + `ds_addr_jibun` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '지번주소', + `ds_tel` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '일반전화', + `ds_rep_phone` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '개인전화', + `ds_email` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '이메일', + `ds_gugun_code` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '구코드', + `ds_designated_at` DATE NULL DEFAULT NULL COMMENT '지정일자', + `ds_state` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=정상, 2=폐업, 3=직권해지', + `ds_regdate` DATETIME NOT NULL COMMENT '등록일시', + PRIMARY KEY (`ds_idx`), + KEY `idx_ds_lg_idx` (`ds_lg_idx`), + KEY `idx_ds_mb_idx` (`ds_mb_idx`), + UNIQUE KEY `uk_ds_shop_no` (`ds_shop_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='지정판매소'; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/writable/database/member_approval_request_add.sql b/writable/database/member_approval_request_add.sql new file mode 100644 index 0000000..eaf8476 --- /dev/null +++ b/writable/database/member_approval_request_add.sql @@ -0,0 +1,22 @@ +-- 기존 DB에 회원가입 역할 승인 요청 테이블 추가 +-- 실행 예: +-- mysql -h 127.0.0.1 -P 3306 -u jongryangje -p jongryangje_dev < writable/database/member_approval_request_add.sql + +SET NAMES utf8mb4; + +CREATE TABLE IF NOT EXISTS `member_approval_request` ( + `mar_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '승인요청 PK', + `mb_idx` INT UNSIGNED NOT NULL COMMENT '회원 FK(member.mb_idx)', + `mar_requested_level` TINYINT UNSIGNED NOT NULL COMMENT '요청 역할(1,2,3)', + `mar_status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT 'pending|approved|rejected', + `mar_request_note` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '요청 메모', + `mar_reject_reason` VARCHAR(255) NULL DEFAULT NULL COMMENT '반려 사유', + `mar_requested_at` DATETIME NOT NULL COMMENT '요청일시', + `mar_requested_by` INT UNSIGNED NULL DEFAULT NULL COMMENT '요청자 mb_idx', + `mar_processed_at` DATETIME NULL DEFAULT NULL COMMENT '처리일시', + `mar_processed_by` INT UNSIGNED NULL DEFAULT NULL COMMENT '처리자 mb_idx', + PRIMARY KEY (`mar_idx`), + KEY `idx_mar_mb_idx` (`mb_idx`), + KEY `idx_mar_status_requested` (`mar_status`, `mar_requested_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='회원가입 역할 승인 요청'; + diff --git a/writable/database/menu_add_lg_idx.sql b/writable/database/menu_add_lg_idx.sql new file mode 100644 index 0000000..576fc18 --- /dev/null +++ b/writable/database/menu_add_lg_idx.sql @@ -0,0 +1,3 @@ +-- 기존 menu 테이블에 지자체(lg_idx) 컬럼 추가 (이미 컬럼이 있으면 에러 무시하고 스킵) +ALTER TABLE `menu` ADD COLUMN `lg_idx` INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '지자체 FK' AFTER `mt_idx`; +ALTER TABLE `menu` ADD KEY `idx_mt_lg` (`mt_idx`, `lg_idx`); diff --git a/writable/database/menu_site_seed_from_csv.sql b/writable/database/menu_site_seed_from_csv.sql new file mode 100644 index 0000000..0f1d239 --- /dev/null +++ b/writable/database/menu_site_seed_from_csv.sql @@ -0,0 +1,292 @@ +-- CSV "종량제_개발목록_20260127(전체 메뉴 - 1차정리).csv" 기반으로 +-- site 타입(menu_type.mt_code='site')의 1차/2차 메뉴를 초기 시드하는 SQL 뼈대입니다. +-- +-- 1행: 1차 메뉴명 리스트 +-- 2행 이후: 각 열이 해당 1차 메뉴의 2차 메뉴명에 해당. +-- +-- 실제 운영 시에는 CSV를 파싱해서 INSERT를 생성하는 스크립트를 사용하는 편이 낫고, +-- 아래 SQL은 구조 이해 및 수동 시드를 위한 참고용입니다. + +-- 1) site용 mt_idx 조회 (예: @mt_site) +SET @mt_site := (SELECT mt_idx FROM menu_type WHERE mt_code = 'site' LIMIT 1); + + +-- 3) 2차 메뉴 예시 +-- CSV의 2행 이후를 바탕으로, 각 1차 메뉴 아래에 2차 메뉴를 추가하는 방식의 예시입니다. +-- 아래 예시는 구조를 보여주기 위한 샘플이며, 실제 라우트(mm_link)는 구현 후에 맞게 수정해야 합니다. + +-- 예: "기본정보관리" 하위 2차 메뉴들 (PWB-030100~ 등) +SET @parent_basic := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '기본정보관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_basic, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '기본 코드 관리' AS mm_name UNION ALL + SELECT 1, '단가 관리' UNION ALL + SELECT 2, '포장 단위 관리' UNION ALL + SELECT 3, '판매 대행소 관리' UNION ALL + SELECT 4, '담당자 관리' UNION ALL + SELECT 5, '업체 관리' UNION ALL + SELECT 6, '무료용 대상자 관리' UNION ALL + SELECT 7, '지정 판매소 관리' UNION ALL + SELECT 8, '지정 판매소 조회' UNION ALL + SELECT 9, '지정 판매소 신규/취소 현황' UNION ALL + SELECT 10, '지정판매소 바코드 출력' UNION ALL + SELECT 11, 'PC -> PDA로 자료 전송' UNION ALL + SELECT 12, 'PDA -> PC로 자료 전송' UNION ALL + SELECT 13, '올린 자료 처리' UNION ALL + SELECT 14, '시찰 처리' UNION ALL + SELECT 15, 'PASSWORD 변경' UNION ALL + SELECT 16, '환경 설정' UNION ALL + SELECT 17, '지정 판매소 현황' +) AS t +WHERE @parent_basic IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_basic + AND m.mm_name = t.mm_name + ); + +-- 2) 1차: 발주 입고 관리 하위 메뉴 +SET @parent_order := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '발주 입고 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_order, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '발주 등록' AS mm_name UNION ALL + SELECT 1, '발주 변경' UNION ALL + SELECT 2, 'LOT-No 디스켓 불출' UNION ALL + SELECT 3, '발주 현황' UNION ALL + SELECT 4, '발주 입고[스캐너]' UNION ALL + SELECT 5, '일괄입고' UNION ALL + SELECT 6, '입고 현황' +) AS t +WHERE @parent_order IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_order + AND m.mm_name = t.mm_name + ); + +-- 3) 1차: 불출 관리 하위 메뉴 +SET @parent_issue := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '불출 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_issue, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '무료 불출 현황' AS mm_name UNION ALL + SELECT 1, '무료용 불출 처리' UNION ALL + SELECT 2, '무료용 불출 취소' +) AS t +WHERE @parent_issue IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_issue + AND m.mm_name = t.mm_name + ); + +-- 4) 1차: 재고 관리 하위 메뉴 +SET @parent_inventory := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '재고 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_inventory, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '재고 현황' AS mm_name UNION ALL + SELECT 1, '실사 관리' UNION ALL + SELECT 2, '실사 선별' UNION ALL + SELECT 3, '실사 선별 조회' UNION ALL + SELECT 4, '실사 등록' UNION ALL + SELECT 5, '실사 재고 조회' UNION ALL + SELECT 6, '실사 오류 조회' UNION ALL + SELECT 7, '실사 선별 취소' UNION ALL + SELECT 8, '실사 등록 취소' +) AS t +WHERE @parent_inventory IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_inventory + AND m.mm_name = t.mm_name + ); + +-- 5) 1차: 판매 관리 하위 메뉴 +SET @parent_sales := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '판매 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_sales, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '전화 접수' AS mm_name UNION ALL + SELECT 1, '전화 접수 관리' UNION ALL + SELECT 2, '지정 판매소 판매' UNION ALL + SELECT 3, '지정 판매소 반품' UNION ALL + SELECT 4, '지정 판매소 판매 취소' UNION ALL + SELECT 5, '지정 판매소 반품 취소' +) AS t +WHERE @parent_sales IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_sales + AND m.mm_name = t.mm_name + ); + +-- 6) 1차: 판매 현황 하위 메뉴 +SET @parent_sales_stats := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '판매 현황' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_sales_stats, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '지정 판매소 일 판매대장' AS mm_name UNION ALL + SELECT 1, '지정 판매소 기간별 판매대장' UNION ALL + SELECT 2, '일계표' UNION ALL + SELECT 3, '기간별 판매현황[일집계]' UNION ALL + SELECT 4, '기간별 판매현황[기간집계]' UNION ALL + SELECT 5, '년 판매 현황' UNION ALL + SELECT 6, '지정 판매소 별 판매현황(수량)' UNION ALL + SELECT 7, '지정 판매소 별 판매현황(금액)' UNION ALL + SELECT 8, '지정판매소별 거래현황' UNION ALL + SELECT 9, '홈텍스 처리' +) AS t +WHERE @parent_sales_stats IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_sales_stats + AND m.mm_name = t.mm_name + ); + +-- 7) 1차: 봉투 수불 관리 하위 메뉴 +SET @parent_flow := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '봉투 수불 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_flow, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '기타 입출고' AS mm_name UNION ALL + SELECT 1, '기간별 봉투 수불 현황' UNION ALL + SELECT 2, '일일 봉투 수불 현황' UNION ALL + SELECT 3, '반품/파기 현황' UNION ALL + SELECT 4, '쓰레기 봉투 수급 계획' UNION ALL + SELECT 5, 'LOT 수불 조회' +) AS t +WHERE @parent_flow IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_flow + AND m.mm_name = t.mm_name + ); + +-- 8) 1차: 통계 분석 관리 하위 메뉴 +SET @parent_analytics := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '통계 분석 관리' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_analytics, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '전년 대비 판매 분석' AS mm_name UNION ALL + SELECT 1, '월별 판매 추이 분석' UNION ALL + SELECT 2, '계절별 판매 추이 분석' +) AS t +WHERE @parent_analytics IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_analytics + AND m.mm_name = t.mm_name + ); + +-- 9) 1차: 창 하위 메뉴 +SET @parent_window := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '창' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_window, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, 'PDA 수정' AS mm_name UNION ALL + SELECT 1, '바둑판식 배열' UNION ALL + SELECT 2, '계단식 배열' UNION ALL + SELECT 3, '계층식 배열' +) AS t +WHERE @parent_window IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_window + AND m.mm_name = t.mm_name + ); + +-- 10) 1차: 도움말 하위 메뉴 +SET @parent_help := ( + SELECT mm_idx FROM menu + WHERE mt_idx = @mt_site AND lg_idx = 1 AND mm_pidx = 0 AND mm_name = '도움말' + LIMIT 1 +); + +INSERT INTO menu (mt_idx, lg_idx, mm_name, mm_link, mm_pidx, mm_dep, mm_num, mm_cnode, mm_level, mm_is_view) +SELECT @mt_site, 1, t.mm_name, '', @parent_help, 1, t.mm_num, 0, '', 'Y' +FROM ( + SELECT 0 AS mm_num, '도움말 항목' AS mm_name UNION ALL + SELECT 1, '원격 요청' UNION ALL + SELECT 2, 'pda 리셋' UNION ALL + SELECT 3, '번호알기' UNION ALL + SELECT 4, 'Data Backup' UNION ALL + SELECT 5, '컴포트 설정' UNION ALL + SELECT 6, 'Version 정보' UNION ALL + SELECT 7, '종료' UNION ALL + SELECT 8, '1GBMS' +) AS t +WHERE @parent_help IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM menu m + WHERE m.mt_idx = @mt_site + AND m.lg_idx = 1 + AND m.mm_pidx = @parent_help + AND m.mm_name = t.mm_name + ); + diff --git a/writable/database/menu_tables.sql b/writable/database/menu_tables.sql new file mode 100644 index 0000000..6b338e0 --- /dev/null +++ b/writable/database/menu_tables.sql @@ -0,0 +1,58 @@ +-- 메뉴 종류 (admin=관리자 상단 메뉴, site=사이트 첫페이지 등) +CREATE TABLE IF NOT EXISTS `menu_type` ( + `mt_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '메뉴종류 PK', + `mt_code` VARCHAR(30) NOT NULL DEFAULT '' COMMENT '코드(admin, site 등)', + `mt_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '표시명', + `mt_sort` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '정렬', + PRIMARY KEY (`mt_idx`), + UNIQUE KEY `uk_mt_code` (`mt_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='메뉴 종류'; + +-- 메뉴 항목 (지자체별 관리, 트리: mm_pidx=0 최상위, mm_dep 깊이, mm_num 형제순서) +CREATE TABLE IF NOT EXISTS `menu` ( + `mm_idx` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '메뉴 PK', + `mt_idx` INT UNSIGNED NOT NULL COMMENT '메뉴종류 FK', + `lg_idx` INT UNSIGNED NOT NULL COMMENT '지자체 FK', + `mm_name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '메뉴명', + `mm_link` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '링크(예: admin/users)', + `mm_pidx` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '부모 메뉴 PK(0=최상위)', + `mm_dep` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '깊이(0,1,2)', + `mm_num` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '형제 내 순서', + `mm_cnode` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '자식 개수', + `mm_level` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '노출 허용 mb_level 쉼표구분(빈값=전체)', + `mm_is_view` CHAR(1) NOT NULL DEFAULT 'Y' COMMENT 'Y=노출, N=숨김', + PRIMARY KEY (`mm_idx`), + KEY `idx_mt_lg` (`mt_idx`, `lg_idx`), + KEY `idx_mm_pidx` (`mm_pidx`), + KEY `idx_mm_dep_num` (`mm_dep`, `mm_num`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='메뉴'; + +-- 초기 데이터: 메뉴 종류 (admin, site) + lg_idx=1 지자체용 기본 1차 메뉴 +INSERT INTO `menu_type` (`mt_code`, `mt_name`, `mt_sort`) VALUES +('admin', '관리자 메뉴', 10), +('site', '사이트 메뉴', 20); + +-- admin 타입, lg_idx=1 기본 1차 관리자 메뉴 +INSERT INTO `menu` (`mt_idx`, `lg_idx`, `mm_name`, `mm_link`, `mm_pidx`, `mm_dep`, `mm_num`, `mm_cnode`, `mm_level`, `mm_is_view`) VALUES +-- mt_idx=1 (admin) +(1, 1, '대시보드', 'admin', 0, 0, 0, 0, '3', 'Y'), +(1, 1, '회원 관리', 'admin/users', 0, 0, 1, 0, '', 'Y'), +(1, 1, '로그인 이력', 'admin/access/login-history', 0, 0, 2, 0, '', 'Y'), +(1, 1, '승인 대기', 'admin/access/approvals', 0, 0, 3, 0, '', 'Y'), +(1, 1, '역할', 'admin/roles', 0, 0, 4, 0, '', 'Y'), +(1, 1, '메뉴', 'admin/menus', 0, 0, 5, 0, '', 'Y'), +(1, 1, '지자체 전환', 'admin/select-local-government', 0, 0, 6, 0, '', 'Y'), +(1, 1, '지자체', 'admin/local-governments', 0, 0, 7, 0, '', 'Y'), +(1, 1, '지정판매소', 'admin/designated-shops', 0, 0, 8, 0, '3', 'Y'), + +-- mt_idx=2 (site) 기본 1차 사이트 메뉴 (링크는 추후 실제 라우트로 변경) +(2, 1, '기본정보관리', 'bag/basic-info', 0, 0, 0, 0, '', 'Y'), +(2, 1, '발주 입고 관리', 'bag/purchase-inbound', 0, 0, 1, 0, '', 'Y'), +(2, 1, '불출 관리', 'bag/issue', 0, 0, 2, 0, '', 'Y'), +(2, 1, '재고 관리', 'bag/inventory', 0, 0, 3, 0, '', 'Y'), +(2, 1, '판매 관리', 'bag/sales', 0, 0, 4, 0, '', 'Y'), +(2, 1, '판매 현황', 'bag/sales-stats', 0, 0, 5, 0, '', 'Y'), +(2, 1, '봉투 수불 관리', 'bag/flow', 0, 0, 6, 0, '', 'Y'), +(2, 1, '통계 분석 관리', 'bag/analytics', 0, 0, 7, 0, '', 'Y'), +(2, 1, '창', 'bag/window', 0, 0, 8, 0, '', 'Y'), +(2, 1, '도움말', 'bag/help', 0, 0, 9, 0, '', 'Y'); diff --git a/writable/database/menu_type_add_site.sql b/writable/database/menu_type_add_site.sql new file mode 100644 index 0000000..54a2b81 --- /dev/null +++ b/writable/database/menu_type_add_site.sql @@ -0,0 +1,34 @@ +-- 기존 DB에 menu_type.site 및 기본 site 1차 메뉴 추가용 스크립트 +-- 주의: mt_idx 값은 실제 DB 상태에 따라 다를 수 있으므로, +-- 아래에서 site용 mt_idx는 서브쿼리로 조회하여 사용한다. + +-- 1) menu_type에 site 타입 추가 (이미 있으면 무시) +INSERT IGNORE INTO `menu_type` (`mt_code`, `mt_name`, `mt_sort`) +VALUES ('site', '사이트 메뉴', 20); + +-- 2) lg_idx=1 기준 기본 1차 사이트 메뉴 추가 +-- (이미 같은 이름/링크가 있으면 중복 INSERT를 피하기 위해 WHERE NOT EXISTS 사용) +INSERT INTO `menu` (`mt_idx`, `lg_idx`, `mm_name`, `mm_link`, `mm_pidx`, `mm_dep`, `mm_num`, `mm_cnode`, `mm_level`, `mm_is_view`) +SELECT mt.mt_idx, 1 AS lg_idx, t.mm_name, t.mm_link, 0 AS mm_pidx, 0 AS mm_dep, t.mm_num, 0 AS mm_cnode, '' AS mm_level, 'Y' AS mm_is_view +FROM ( + SELECT 0 AS mm_num, '기본정보관리' AS mm_name, 'bag/basic-info' AS mm_link UNION ALL + SELECT 1, '발주 입고 관리', 'bag/purchase-inbound' UNION ALL + SELECT 2, '불출 관리', 'bag/issue' UNION ALL + SELECT 3, '재고 관리', 'bag/inventory' UNION ALL + SELECT 4, '판매 관리', 'bag/sales' UNION ALL + SELECT 5, '판매 현황', 'bag/sales-stats' UNION ALL + SELECT 6, '봉투 수불 관리', 'bag/flow' UNION ALL + SELECT 7, '통계 분석 관리', 'bag/analytics' UNION ALL + SELECT 8, '창', 'bag/window' UNION ALL + SELECT 9, '도움말', 'bag/help' +) AS t +JOIN `menu_type` mt ON mt.mt_code = 'site' +WHERE NOT EXISTS ( + SELECT 1 FROM `menu` m + WHERE m.mt_idx = mt.mt_idx + AND m.lg_idx = 1 + AND m.mm_pidx = 0 + AND m.mm_name = t.mm_name + AND m.mm_link = t.mm_link +); + diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/debugbar/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/index.html b/writable/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/logs/index.html b/writable/logs/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/logs/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/session/index.html b/writable/session/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/session/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/uploads/index.html b/writable/uploads/index.html new file mode 100755 index 0000000..b702fbc --- /dev/null +++ b/writable/uploads/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + +