Merge branch 'main-design-layout' of https://git.eactive.synology.me:8090/kjb-eapim/eapim-portal into main-design-layout

This commit is contained in:
Rinjae
2025-11-18 10:03:53 +09:00
49 changed files with 1911 additions and 1284 deletions
@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/agreements")
public class AgreementsController {
public static final String TERMS_AGREEMENTS = "fragment/kbank/terms_agreements";
public static final String TERMS_AGREEMENTS = "fragment/kjbank/terms_agreements";
private final AgreementsFacade agreementsFacade;
@@ -119,7 +119,7 @@ public class CommissionController {
@PostMapping()
public ResponseEntity<?> list(@RequestBody CommissionSearch search) {
CommissionDTO commissionDTO = null;
search.setProvider(providerCode);
search.setPartnerCode(SecurityUtil.getUserOrg().getOrgCode());
if (!StringUtils.isEmpty(search.getPartnerCode())) {
@@ -157,50 +157,6 @@ public class CommissionController {
return ErrorUtil.create("fail.commission.needPartnerCode");
}
@GetMapping("/print1/{year}/{month}")
public ResponseEntity<?> print(
@PathVariable("year") String year,
@PathVariable("month") String month) {
CommissionDTO commissionDTO = null;
CommissionSearch search = new CommissionSearch();
search.setOrganization(SecurityUtil.getPortalAuthenticatedUser().getPortalOrg());
search.setProvider(providerCode);
search.setYear(year);
search.setMonth(month);
search.setPartnerCode(SecurityUtil.getUserOrg().getOrgCode());
if (!StringUtils.isEmpty(search.getPartnerCode())) {
try {
String url = obmUrl + Constants.COMMISSION_PRINT_URL;
String result = externalService.getResponseHttpPost(url, toJson(search));
HashMap<String, Object> returnObj = new ObjectMapper().readValue(result, HashMap.class);
if (StringUtils.pathEquals(search.getPartnerCode(), "000002-01")) {
log.debug("Found Together : " + search.getPartnerCode());
search.setPartnerCode("000002-02");
String togetherResult = externalService.getResponseHttpPost(url, toJson(search));
HashMap<String, Object> togetherLendingReturnObj = new ObjectMapper().readValue(togetherResult, HashMap.class);
log.debug("togetherLendingReturnObj : " + togetherLendingReturnObj.toString());
if (!StringUtils.isEmpty(togetherLendingReturnObj.get("error"))) {
HashMap<String, Object> error = (HashMap) togetherLendingReturnObj.get("error");
return ErrorUtil.create("fail.commission.serverError", error.get("message").toString());
}
HashMap<String, Object> mergeMap = mergeCommissionData(returnObj, togetherLendingReturnObj);
result = new ObjectMapper().writeValueAsString(mergeMap);
}
commissionDTO = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readValue(result, CommissionDTO.class);
} catch (Exception e) {
log.warn(e.getMessage(), e);
return ErrorUtil.create("fail.commission.list", "수수료 조회에 실패하였습니다.");
}
return ResponseEntity.ok().body(commissionDTO);
}
return ErrorUtil.create("fail.commission.needPartnerCode");
}
private String toJson(CommissionSearch search) {
try {
Map<String, String> jsonMap = new HashMap<>();
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,8 +5,8 @@
// Color Palette - Vibrant and Modern
// Primary colors
$primary-blue: #4B9BFF; // Bright blue (main brand color)
$secondary-blue: #2E7FF7; // Deep blue
$primary-blue: #0049b4; // 광주은행 블루
$secondary-blue: #c3dfea; // Deep blue
$accent-cyan: #00D4FF; // Sky blue accent
$accent-yellow: #FFD93D; // Yellow accent
$accent-orange: #FF6B6B; // Orange accent
@@ -23,9 +23,9 @@
.faq-question {
color: $primary-blue;
&::before {
background: $gradient-primary;
}
//&::before {
// background: $gradient-primary;
//}
.faq-icon {
transform: rotate(180deg);
@@ -128,7 +128,7 @@
display: flex;
align-items: center;
justify-content: center;
background: $gradient-primary;
background: $primary-blue;
color: $white;
border-radius: $border-radius-circle;
font-size: $font-size-sm;
@@ -31,7 +31,7 @@
// Button variants
&-primary {
background: $gradient-primary;
background: $primary-blue;
color: $white;
box-shadow: $shadow-md;
@@ -46,9 +46,8 @@
}
&-secondary {
background: $white;
color: $primary-blue;
border: 2px solid $primary-blue;
background: $secondary-blue;
color: #6e7780;
&:hover {
background: $light-bg;
@@ -475,4 +474,4 @@
i {
font-size: 14px;
}
}
}
@@ -332,30 +332,30 @@
}
}
button {
padding: $spacing-sm $spacing-lg;
background: $gradient-primary;
color: $white;
border: none;
border-radius: $border-radius-md;
font-size: $font-size-sm;
font-weight: $font-weight-medium;
cursor: pointer;
transition: $transition-base;
white-space: nowrap;
&:hover {
transform: translateY(-2px);
box-shadow: $shadow-md;
}
&:active {
transform: translateY(0);
}
i {
margin-right: $spacing-xs;
}
}
//button {
// padding: $spacing-sm $spacing-lg;
// background: $gradient-primary;
// color: $white;
// border: none;
// border-radius: $border-radius-md;
// font-size: $font-size-sm;
// font-weight: $font-weight-medium;
// cursor: pointer;
// transition: $transition-base;
// white-space: nowrap;
//
// &:hover {
// transform: translateY(-2px);
// box-shadow: $shadow-md;
// }
//
// &:active {
// transform: translateY(0);
// }
//
// i {
// margin-right: $spacing-xs;
// }
//}
}
}
+1
View File
@@ -51,6 +51,7 @@
@import 'pages/org-register';
@import 'pages/user-management';
@import 'pages/commission';
@import 'pages/terms-agreements';
// 6. Themes
@import 'themes/dark';
@@ -1004,54 +1004,30 @@
@media (max-width: $breakpoint-sm) {
flex-direction: column;
width: 100%;
.btn-primary,
.btn-secondary {
width: 100%;
justify-content: center;
}
}
.btn-primary,
.btn-secondary {
display: inline-flex;
align-items: center;
padding: 0 $spacing-md $spacing-md;
gap: $spacing-sm;
padding: 12px 24px;
border-radius: $border-radius-md;
font-size: $font-size-base;
font-weight: $font-weight-medium;
transition: $transition-base;
text-decoration: none;
border: none;
cursor: pointer;
.icon {
font-size: 18px;
}
}
.btn-primary {
background: $gradient-primary;
color: $white;
box-shadow: $shadow-md;
// Button styles for mobile
.btn,
.btn-primary,
.btn-secondary,
.btn-cancel {
@media (max-width: $breakpoint-sm) {
width: 100%;
min-height: 48px;
padding: 14px $spacing-lg;
font-size: $font-size-base;
justify-content: center;
&:hover {
transform: translateY(-2px);
box-shadow: $shadow-lg;
}
}
.icon {
font-size: 18px;
}
.btn-secondary {
background: $white;
color: $text-dark;
border: 1px solid $border-gray;
&:hover {
background: $gray-bg;
border-color: $primary-blue;
color: $primary-blue;
svg {
width: 18px;
height: 18px;
}
}
}
}
@@ -1303,6 +1279,13 @@
gap: $spacing-md;
flex-wrap: wrap;
@media (max-width: $breakpoint-sm) {
flex-direction: column;
align-items: stretch;
gap: $spacing-sm;
padding: 0 $spacing-md;
}
.btn-primary,
.btn-secondary {
display: inline-flex;
@@ -1320,6 +1303,13 @@
.icon {
font-size: 18px;
}
@media (max-width: $breakpoint-sm) {
width: 100%;
min-height: 48px;
padding: 14px $spacing-lg;
justify-content: center;
}
}
.btn-primary {
@@ -45,6 +45,7 @@
border: 1px solid $border-gray;
border-radius: $border-radius-sm;
font-size: $font-size-sm;
min-width: 100px;
}
}
@@ -258,12 +259,15 @@
}
// Commission Print Page Specific
.commission-print-page {
// Note: commissionPrint.html uses body class for scoping
body.commission-print-page {
font-size: 12px;
width: 600px;
margin: 90px;
font-family: 'Noto Sans KR', -apple-system, sans-serif;
body {
width: 600px;
margin: 90px;
div {
position: relative;
}
table {
@@ -289,9 +293,32 @@
h2 {
margin-top: $spacing-2xl;
float: left;
}
p {
line-height: 1.6;
&[style*="float: right"] {
margin-top: 25px;
}
}
// Print buttons
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn-primary {
background: #667eea;
color: white;
&:hover {
background: #5a67d8;
}
}
}
@@ -102,14 +102,14 @@
align-items: center;
justify-content: space-between;
padding: $spacing-lg $spacing-xl;
background: linear-gradient(135deg, $primary-blue 0%, $secondary-blue 100%);
background: #EDF9FE;
border-radius: $border-radius-md;
margin-bottom: $spacing-xl;
h3 {
font-size: $font-size-lg;
font-weight: $font-weight-semibold;
color: $white;
font-weight: $font-weight-regular;
color: #515961;
margin: 0;
}
@@ -0,0 +1,497 @@
// -----------------------------------------------------------------------------
// Terms and Agreements Page - Modern Design
// 이용약관 개인정보처리방침 페이지
// -----------------------------------------------------------------------------
// Page Container
.terms-page {
min-height: calc(100vh - 140px);
background: $gray-bg;
padding: $spacing-3xl $spacing-lg;
@media (max-width: $breakpoint-sm) {
padding: $spacing-2xl $spacing-md;
}
}
.terms-container {
max-width: $container-max-width;
margin: 0 auto;
}
// Page Header
.terms-header {
margin-bottom: $spacing-3xl;
@media (max-width: $breakpoint-sm) {
margin-bottom: $spacing-2xl;
}
.page-title {
font-size: $font-size-3xl;
font-weight: $font-weight-bold;
color: $text-dark;
margin-bottom: $spacing-md;
background: $gradient-primary;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-2xl;
}
}
.page-description {
font-size: $font-size-base;
color: $text-gray;
line-height: $line-height-normal;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-sm;
}
}
}
// Terms Content Card
.terms-content-card {
background: $white;
border-radius: $border-radius-lg;
box-shadow: $shadow-md;
overflow: hidden;
}
// Tab Navigation
.terms-tabs {
display: flex;
gap: 0;
background: $gray-bg;
padding: $spacing-xs;
border-bottom: 1px solid $border-gray;
@media (max-width: $breakpoint-sm) {
padding: $spacing-xs;
}
.tab-link {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: $spacing-sm;
padding: $spacing-md $spacing-lg;
font-size: $font-size-base;
font-weight: $font-weight-semibold;
color: $text-gray;
text-decoration: none;
background: transparent;
border-radius: $border-radius-md;
transition: $transition-base;
text-align: center;
@media (max-width: $breakpoint-sm) {
padding: $spacing-sm $spacing-md;
font-size: $font-size-sm;
gap: $spacing-xs;
}
i {
font-size: $font-size-md;
transition: $transition-base;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-base;
}
}
&:hover {
color: $primary-blue;
background: rgba($primary-blue, 0.05);
i {
transform: scale(1.1);
}
}
&.active {
color: $white;
background: $primary-blue;
box-shadow: $shadow-sm;
i {
color: $white;
}
}
}
}
// Version Selector
.terms-selector {
padding: $spacing-lg $spacing-2xl;
background: $light-bg;
border-bottom: 1px solid $border-gray;
@media (max-width: $breakpoint-sm) {
padding: $spacing-md $spacing-lg;
}
form {
max-width: 400px;
}
.custom-select {
position: relative;
cursor: pointer;
.select-selected {
display: flex;
align-items: center;
gap: $spacing-sm;
padding: $spacing-md $spacing-lg;
background: $white;
border: 2px solid $border-gray;
border-radius: $border-radius-md;
font-size: $font-size-sm;
font-weight: $font-weight-medium;
color: $text-dark;
transition: $transition-base;
cursor: pointer;
@media (max-width: $breakpoint-sm) {
padding: $spacing-sm $spacing-md;
font-size: $font-size-xs;
}
i {
&:first-child {
color: $primary-blue;
}
&:last-child {
margin-left: auto;
font-size: $font-size-xs;
color: $text-gray;
transition: $transition-base;
}
}
span {
font-weight: $font-weight-semibold;
color: $primary-blue;
}
&:hover {
border-color: $primary-blue;
box-shadow: 0 0 0 3px rgba($primary-blue, 0.1);
}
&.select-arrow-active {
border-color: $primary-blue;
i:last-child {
transform: rotate(180deg);
}
}
}
.select-items {
position: absolute;
top: calc(100% + $spacing-xs);
left: 0;
right: 0;
background: $white;
border: 2px solid $primary-blue;
border-radius: $border-radius-md;
box-shadow: $shadow-lg;
max-height: 240px;
overflow-y: auto;
z-index: $z-index-dropdown;
list-style: none;
padding: $spacing-xs;
margin: 0;
&.select-hide {
display: none;
}
li {
padding: $spacing-sm $spacing-md;
font-size: $font-size-sm;
color: $text-dark;
border-radius: $border-radius-sm;
cursor: pointer;
transition: $transition-base;
@media (max-width: $breakpoint-sm) {
padding: $spacing-xs $spacing-sm;
font-size: $font-size-xs;
}
&:hover {
background: $light-bg;
color: $primary-blue;
}
&.selected {
background: $primary-blue;
color: $white;
font-weight: $font-weight-semibold;
}
}
}
}
}
// Terms Content
.terms-content {
padding: $spacing-3xl $spacing-2xl;
min-height: 400px;
@media (max-width: $breakpoint-sm) {
padding: $spacing-2xl $spacing-lg;
min-height: 300px;
}
.content-body {
font-size: $font-size-base;
color: $text-dark;
line-height: $line-height-loose;
white-space: pre-wrap;
word-wrap: break-word;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-sm;
}
// Content formatting
p {
margin-bottom: $spacing-md;
&:last-child {
margin-bottom: 0;
}
}
h1, h2, h3, h4, h5, h6 {
margin-top: $spacing-xl;
margin-bottom: $spacing-md;
font-weight: $font-weight-semibold;
color: $text-dark;
line-height: $line-height-tight;
&:first-child {
margin-top: 0;
}
}
h1 {
font-size: $font-size-2xl;
font-weight: $font-weight-bold;
padding-bottom: $spacing-md;
border-bottom: 2px solid $border-gray;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-xl;
}
}
h2 {
font-size: $font-size-xl;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-lg;
}
}
h3 {
font-size: $font-size-lg;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-base;
}
}
strong {
font-weight: $font-weight-bold;
color: $text-dark;
}
em {
font-style: italic;
color: $text-gray;
}
a {
color: $primary-blue;
text-decoration: underline;
transition: $transition-base;
&:hover {
color: $secondary-blue;
}
}
ul, ol {
margin: $spacing-md 0;
padding-left: $spacing-2xl;
@media (max-width: $breakpoint-sm) {
padding-left: $spacing-lg;
}
}
ul {
list-style-type: disc;
}
ol {
list-style-type: decimal;
}
li {
margin-bottom: $spacing-sm;
line-height: $line-height-normal;
&:last-child {
margin-bottom: 0;
}
}
blockquote {
border-left: 4px solid $primary-blue;
padding-left: $spacing-lg;
margin: $spacing-lg 0;
color: $text-gray;
font-style: italic;
background: $gray-bg;
padding: $spacing-md $spacing-lg;
border-radius: 0 $border-radius-md $border-radius-md 0;
@media (max-width: $breakpoint-sm) {
padding: $spacing-sm $spacing-md;
}
}
code {
background: $gray-bg;
padding: 2px 6px;
border-radius: $border-radius-sm;
font-family: $font-family-mono;
font-size: 0.9em;
color: $primary-blue;
}
pre {
background: $gray-bg;
border: 1px solid $border-gray;
border-radius: $border-radius-md;
padding: $spacing-md;
overflow-x: auto;
margin: $spacing-lg 0;
@media (max-width: $breakpoint-sm) {
padding: $spacing-sm;
}
code {
background: transparent;
padding: 0;
color: $text-dark;
}
}
table {
width: 100%;
border-collapse: collapse;
margin: $spacing-lg 0;
border: 1px solid $border-gray;
border-radius: $border-radius-md;
overflow: hidden;
font-size: $font-size-sm;
@media (max-width: $breakpoint-sm) {
font-size: $font-size-xs;
}
th {
background: $light-bg;
padding: $spacing-sm $spacing-md;
text-align: left;
font-weight: $font-weight-semibold;
color: $text-dark;
border-bottom: 2px solid $border-gray;
@media (max-width: $breakpoint-sm) {
padding: $spacing-xs $spacing-sm;
}
}
td {
padding: $spacing-sm $spacing-md;
border-bottom: 1px solid $border-gray;
color: $text-dark;
@media (max-width: $breakpoint-sm) {
padding: $spacing-xs $spacing-sm;
}
}
tr {
&:last-child td {
border-bottom: none;
}
&:hover {
background: $gray-bg;
}
}
}
hr {
border: none;
border-top: 1px solid $border-gray;
margin: $spacing-2xl 0;
}
// Article/Section numbering
.article {
margin-top: $spacing-2xl;
padding-top: $spacing-lg;
border-top: 1px solid $border-gray;
&:first-child {
margin-top: 0;
padding-top: 0;
border-top: none;
}
}
.section-number {
display: inline-block;
min-width: 30px;
color: $primary-blue;
font-weight: $font-weight-bold;
}
}
}
// Scrollbar styling for select dropdown
.terms-selector .select-items {
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: $gray-bg;
border-radius: $border-radius-sm;
}
&::-webkit-scrollbar-thumb {
background: $primary-blue;
border-radius: $border-radius-sm;
&:hover {
background: $secondary-blue;
}
}
}
@@ -50,36 +50,6 @@
gap: $spacing-md;
}
.btn-create-user,
.btn-create-user-large {
display: inline-flex;
align-items: center;
gap: $spacing-sm;
padding: 12px $spacing-xl;
background: $gradient-primary;
color: $white;
font-size: $font-size-base;
font-weight: $font-weight-semibold;
border: none;
border-radius: $border-radius-lg;
cursor: pointer;
transition: $transition-base;
box-shadow: $shadow-md;
&:hover {
transform: translateY(-2px);
box-shadow: $shadow-lg;
}
&:active {
transform: translateY(0);
}
.btn-icon {
font-size: $font-size-lg;
}
}
.btn-create-user-large {
padding: $spacing-md $spacing-2xl;
font-size: $font-size-md;
@@ -315,69 +285,6 @@
flex-wrap: wrap;
gap: $spacing-xs;
align-items: center;
.btn-action {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
font-size: $font-size-xs;
font-weight: $font-weight-medium;
border: none;
border-radius: $border-radius-md;
cursor: pointer;
transition: $transition-base;
white-space: nowrap;
&.btn-sm {
padding: 4px 10px;
font-size: 11px;
}
&.btn-primary {
background-color: $primary-blue;
color: $white;
&:hover {
background-color: darken($primary-blue, 10%);
box-shadow: $shadow-sm;
}
}
&.btn-secondary {
background-color: $text-gray;
color: $white;
&:hover {
background-color: darken($text-gray, 10%);
box-shadow: $shadow-sm;
}
}
&.btn-danger {
background-color: $accent-orange;
color: $white;
&:hover {
background-color: darken($accent-orange, 10%);
box-shadow: $shadow-sm;
}
}
&.btn-warning {
background-color: $accent-yellow;
color: $gray-800;
&:hover {
background-color: darken($accent-yellow, 10%);
box-shadow: $shadow-sm;
}
}
&:active {
transform: scale(0.98);
}
}
}
// Empty State
@@ -622,35 +529,3 @@
flex-direction: column;
}
}
.btn-secondary {
display: inline-flex;
align-items: center;
gap: $spacing-sm;
padding: 12px $spacing-xl;
background-color: $white;
color: $text-dark;
font-size: $font-size-base;
font-weight: $font-weight-medium;
border: 2px solid $border-gray;
border-radius: $border-radius-lg;
text-decoration: none;
cursor: pointer;
transition: $transition-base;
&:hover {
background-color: $gray-bg;
border-color: $primary-blue;
color: $primary-blue;
transform: translateY(-2px);
box-shadow: $shadow-sm;
}
&:active {
transform: translateY(0);
}
i {
font-size: $font-size-base;
}
}
@@ -3,22 +3,15 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_base_layout}">
<head>
<title>수수료 관리</title>
<title>수수료 관리</title>
</head>
<body>
<section layout:fragment="contentFragment" class="content">
<div class="row wrap" style="max-width: 1400px; margin: 0 auto; padding: 20px;">
<div class="col-md-12">
<h2><strong>기관 수수료 관리</strong></h2>
<p class="searchInfo">
<button class="btn btn-default" onclick="downloadExcel()" style="display:none;">다운로드</button>
</p>
<p class="searchInfo">
<button id="printBtn" class="btn btn-default" style="margin-left: 5px; display:none;" onclick="printCommission()">
<span>청구서 출력</span>
</button>
</p>
<div class="searchBox row-two" style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; display: flex; align-items: center; gap: 20px; flex-wrap: wrap;">
<div class="row wrap" style="max-width: 1400px; margin: 0 auto; padding: 20px;">
<div class="col-md-12">
<h2><strong>기관 수수료 관리</strong></h2>
<div class="searchBox row-two" style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; display: flex; align-items: center; gap: 20px; flex-wrap: wrap;">
<span class="form-inline" style="display: flex; align-items: center; gap: 10px;">
<label for="providers" style="font-weight: 500; min-width: 80px;">제공기관</label>
<select id="providers" class="form-control">
@@ -27,19 +20,20 @@
<option value="2">한국은행</option>
</select>
</span>
<span class="form-inline" style="display: flex; align-items: center; gap: 10px;">
<span class="form-inline" style="display: flex; align-items: center; gap: 10px;">
<label for="organizations" style="font-weight: 500; min-width: 80px;">이용기관</label>
<select id="organizations" class="form-control">
<option value="">- 선택 -</option>
<option value="1" selected th:text="${organization?.orgName ?: 'ABC 핀테크'}"></option>
</select>
</span>
<span class="form-inline" style="display: flex; align-items: center; gap: 10px;">
<span class="form-inline" style="display: flex; align-items: center; gap: 10px;">
<label for="forYear" style="font-weight: 500; min-width: 80px;">조회기간</label>
<select id="forYear" class="form-control">
<option value="">- 선택 -</option>
<option value="2023">2023</option>
<option value="2024" selected>2024</option>
<option value="2024">2024</option>
<option value="2025" selected>2025</option>
</select> <span></span>&nbsp;&nbsp;
<select id="forMonth" class="form-control">
<option value="">- 선택 -</option>
@@ -57,274 +51,246 @@
<option value="12">12</option>
</select> <span></span>
</span>
<span class="btnBox" style="margin-left: auto;">
<span class="btnBox" style="margin-left: auto;">
<button type="button" class="btn btn-primary" onclick="loadData()">
<span class="glyphicon glyphicon-search"></span>&nbsp;<span>조회</span>
<span class="fa fa-search"></span><span>조회</span>
</button>
<button type="button" id="printBtn" class="btn btn-secondary" style="margin-left: 5px; display:none;" onclick="printCommission()">
<span>청구서 출력</span>
</button>
</span>
</div>
<p class="voffset3" style="color: #dc3545; margin-top: 30px;">
이용기관은 매월 1~5일 전월 수수료 조회 가능하며, 10일 확정금액으로 정산됩니다. <br/>
금액이상시 담당자 연락 및 조정요청 하시기 바랍니다. (매월 1~5일 수수료 조회, 6~9일 수수료 조정 및 확정, 10일 정산)
</p>
</div>
<p class="voffset3" style="color: #dc3545; margin-top: 30px;">
이용기관은 매월 1~5일 전월 수수료 조회 가능하며, 10일 확정금액으로 정산됩니다. <br/>
금액이상시 담당자 연락 및 조정요청 하시기 바랍니다. (매월 1~5일 수수료 조회, 6~9일 수수료 조정 및 확정, 10일 정산)
</p>
<!-- API 수수료 테이블 -->
<div class="table-responsive voffset3" style="overflow-x: auto; margin-top: 30px;">
<table class="table table-bordered border-type" style="border: 2px solid #dee2e6;">
<colgroup>
<col style="width:6%"/>
<col style="width:16%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col />
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th rowspan="2">API 명</th>
<th colspan="4">조정 전</th>
<th colspan="4">조정 후</th>
<th rowspan="2">조정사유</th>
</tr>
<tr>
<th>처리<br/>건수</th>
<th>적용<br/>수수료(원)</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상금액</th>
<th>조정<br/>건수</th>
<th>조정<br/>수수료(원)</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상금액</th>
</tr>
</thead>
<tbody id="apiTableBody">
<!-- 동적 생성 -->
</tbody>
</table>
<!-- API 수수료 테이블 -->
<div class="table-responsive voffset3" style="overflow-x: auto; margin-top: 30px;">
<table class="table table-bordered border-type" style="border: 2px solid #dee2e6;">
<colgroup>
<col style="width:6%"/>
<col style="width:16%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col style="width:8%"/>
<col/>
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th rowspan="2">API 명</th>
<th colspan="4">조정 전</th>
<th colspan="4">조정 후</th>
<th rowspan="2">조정사유</th>
</tr>
<tr>
<th>처리<br/>건수</th>
<th>적용<br/>수수료(원)</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상금액</th>
<th>조정<br/>건수</th>
<th>조정<br/>수수료(원)</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상금액</th>
</tr>
</thead>
<tbody id="apiTableBody">
<!-- 동적 생성 -->
</tbody>
</table>
<!-- 판매 수수료 테이블 -->
<table class="table table-bordered border-type voffset3" style="border: 2px solid #dee2e6; margin-top: 30px;">
<colgroup>
<col style="width: 6%;">
<col style="width: 8%;">
<col style="width: 8%;">
<col style="width: 5%;">
<col style="width: 5%;">
<col style="width: 7%;">
<col style="width: 6%;">
<col style="width: 6%;">
<col style="width: 7%;">
<col style="width: 7%;">
<col style="width: 6%;">
<col style="width: 6%;">
<col style="width: 7%;">
<col style="width: 7%;">
<col>
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th rowspan="2">과금대상<br/>업무</th>
<th rowspan="2">수수료<br/>유형</th>
<th rowspan="2">과금<br/>기준</th>
<th rowspan="2">값구분</th>
<th rowspan="2">판매액</th>
<th colspan="4">조정 전</th>
<th colspan="4">조정 후</th>
<th rowspan="2">조정사유</th>
</tr>
<tr>
<th>적용<br/>수수료</th>
<th>처리<br/>건수</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상수수료</th>
<th>적용<br/>수수료</th>
<th>처리<br/>건수</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상수수료</th>
</tr>
</thead>
<tbody id="saleTableBody">
<!-- 동적 생성 -->
</tbody>
</table>
<!-- 판매 수수료 테이블 -->
<table class="table table-bordered border-type voffset3" style="border: 2px solid #dee2e6; margin-top: 30px;">
<colgroup>
<col style="width: 6%;">
<col style="width: 8%;">
<col style="width: 8%;">
<col style="width: 5%;">
<col style="width: 5%;">
<col style="width: 7%;">
<col style="width: 6%;">
<col style="width: 6%;">
<col style="width: 7%;">
<col style="width: 7%;">
<col style="width: 6%;">
<col style="width: 6%;">
<col style="width: 7%;">
<col style="width: 7%;">
<col>
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th rowspan="2">과금대상<br/>업무</th>
<th rowspan="2">수수료<br/>유형</th>
<th rowspan="2">과금<br/>기준</th>
<th rowspan="2">값구분</th>
<th rowspan="2">판매액</th>
<th colspan="4">조정 전</th>
<th colspan="4">조정 후</th>
<th rowspan="2">조정사유</th>
</tr>
<tr>
<th>적용<br/>수수료</th>
<th>처리<br/>건수</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상수수료</th>
<th>적용<br/>수수료</th>
<th>처리<br/>건수</th>
<th>최저<br/>수수료</th>
<th>출금<br/>예상수수료</th>
</tr>
</thead>
<tbody id="saleTableBody">
<!-- 동적 생성 -->
</tbody>
</table>
<!-- 합계 테이블 -->
<table class="table table-bordered border-type voffset3" style="border: 2px solid #dee2e6; margin-top: 30px;">
<colgroup>
<col />
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%" />
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th colspan="3">조정 전</th>
<th colspan="3">조정 후</th>
</tr>
<tr>
<th>판매액</th>
<th>처리건수(건)</th>
<th>출금예상금액</th>
<th>판매액</th>
<th>처리건수(건)</th>
<th>출금예상금액</th>
</tr>
</thead>
<tbody>
<tr class="bg-warning" style="background-color: #fff3cd !important;">
<td class="text-center"><strong id="totalTitle">2024년 3월 합계</strong></td>
<td class="text-right"><strong id="totalSalesAmount1">0</strong></td>
<td class="text-right"><strong id="totalCount1">0</strong></td>
<td class="text-right"><strong class="color_blue" style="font-size:16px; color: #007bff;" id="totalAmount1">0</strong></td>
<td class="text-right"><strong id="totalSalesAmount2">0</strong></td>
<td class="text-right"><strong id="totalCount2">0</strong></td>
<td class="text-right"><strong class="color_blue" style="font-size:16px; color: #007bff;" id="totalAmount2">0</strong></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 합계 테이블 -->
<table class="table table-bordered border-type voffset3" style="border: 2px solid #dee2e6; margin-top: 30px;">
<colgroup>
<col/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
<col style="width: 13%"/>
</colgroup>
<thead>
<tr>
<th rowspan="2">구분</th>
<th colspan="3">조정 전</th>
<th colspan="3">조정 후</th>
</tr>
<tr>
<th>판매액</th>
<th>처리건수(건)</th>
<th>출금예상금액</th>
<th>판매액</th>
<th>처리건수(건)</th>
<th>출금예상금액</th>
</tr>
</thead>
<tbody>
<tr class="bg-warning" style="background-color: #fff3cd !important;">
<td class="text-center"><strong id="totalTitle">합계</strong></td>
<td class="text-right"><strong id="totalSalesAmount1">-</strong></td>
<td class="text-right"><strong id="totalCount1">-</strong></td>
<td class="text-right"><strong class="color_blue" style="font-size:16px; color: #007bff;" id="totalAmount1">-</strong></td>
<td class="text-right"><strong id="totalSalesAmount2">-</strong></td>
<td class="text-right"><strong id="totalCount2">-</strong></td>
<td class="text-right"><strong class="color_blue" style="font-size:16px; color: #007bff;" id="totalAmount2">-</strong></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<th:block layout:fragment="contentScript">
<script th:inline="javascript">
// 샘플 데이터
const sampleData = {
apiCommissions: [
{
name: '계좌잔액조회',
count1: 20543, fee1: 50, min1: 500000, amount1: 1027150,
count2: 20543, fee2: 50, min2: 500000, amount2: 1027150,
reason: ''
},
{
name: '거래내역조회',
count1: 11876, fee1: 80, min1: 500000, amount1: 950080,
count2: 11876, fee2: 80, min2: 500000, amount2: 950080,
reason: ''
},
{
name: '송금 API',
count1: 4892, fee1: 200, min1: 500000, amount1: 978400,
count2: 4892, fee2: 200, min2: 500000, amount2: 978400,
reason: ''
},
{
name: '본인인증 API',
count1: 2341, fee1: 150, min1: 300000, amount1: 351150,
count2: 2100, fee2: 150, min2: 300000, amount2: 315000,
reason: '오류건 제외'
}
],
saleCommissions: [
{
name: '개인대출 상품 A',
type: '정률',
base: '금액',
division: '원',
salesAmount: 1050000000,
fee1: 0.025, count1: 55, min1: 100000, amount1: 275000,
fee2: 0.025, count2: 55, min2: 100000, amount2: 275000,
reason: ''
},
{
name: '기업대출 상품 B',
type: '정액',
base: '건',
division: '건',
salesAmount: 0,
fee1: 8000, count1: 21, min1: 100000, amount1: 168000,
fee2: 8000, count2: 21, min2: 100000, amount2: 168000,
reason: ''
},
{
name: '소상공인 대출 C',
type: '정액',
base: '건',
division: '건',
salesAmount: 0,
fee1: 3000, count1: 30, min1: 50000, amount1: 90000,
fee2: 3000, count2: 28, min2: 50000, amount2: 84000,
reason: '취소건 제외'
}
]
};
<script th:inline="javascript">
function formatNumber(num) {
return new Intl.NumberFormat('ko-KR').format(num);
}
function formatNumber(num) {
return new Intl.NumberFormat('ko-KR').format(num);
function loadData() {
const year = document.getElementById('forYear').value;
const month = document.getElementById('forMonth').value;
if (!year || !month) {
customPopups.showAlert('조회 기간을 선택해주세요.');
return;
}
// 서버에서 데이터 조회 API 호출
fetch('/commission', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': /*[[${_csrf.token}]]*/ ''
},
body: JSON.stringify({
year: year,
month: month
})
})
.then(response => {
if (!response.ok) {
throw new Error('데이터 조회에 실패했습니다.');
}
return response.json();
})
.then(data => renderCommissionData(data, year, month))
.catch(error => {
console.error('Error:', error);
customPopups.showAlert('데이터 조회 중 오류가 발생했습니다.');
});
}
function renderCommissionData(data, year, month) {
// API 수수료 항목 필터링
const apiCommissions = data.list.filter(item => item.paymentTargetType === '01');
const saleCommissions = data.list.filter(item => item.paymentTargetType !== '01');
// API 수수료 테이블 렌더링
const apiTableBody = document.getElementById('apiTableBody');
apiTableBody.innerHTML = '';
let apiTotal1 = 0;
let apiTotal2 = 0;
let apiCount1 = 0;
let apiCount2 = 0;
apiCommissions.forEach((item, index) => {
if (index === 0) {
apiTableBody.innerHTML += `
<tr>
<td rowspan="${apiCommissions.length}" class="text-center">API<br/>수수료</td>
<td class="text-left">${item.paymentTargetName}</td>
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
<td class="text-right">${formatNumber(item.value || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum || 0)}</span></td>
<td class="text-right"><strong style="color: #007bff;">${formatNumber(item.totalCount2 || 0)}</strong></td>
<td class="text-right">${formatNumber(item.value2 || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum2 || 0)}</span></td>
<td>${item.changeReason2 || ''}</td>
</tr>
`;
} else {
apiTableBody.innerHTML += `
<tr>
<td class="text-left">${item.paymentTargetName}</td>
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
<td class="text-right">${formatNumber(item.value || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum || 0)}</span></td>
<td class="text-right"><strong style="color: #007bff;">${formatNumber(item.totalCount2 || 0)}</strong></td>
<td class="text-right">${formatNumber(item.value2 || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum2 || 0)}</span></td>
<td>${item.changeReason2 || ''}</td>
</tr>
`;
}
apiTotal1 += parseFloat(item.sum || 0);
apiTotal2 += parseFloat(item.sum2 || 0);
apiCount1 += parseInt(item.totalCount || 0);
apiCount2 += parseInt(item.totalCount2 || 0);
});
function loadData() {
const year = document.getElementById('forYear').value;
const month = document.getElementById('forMonth').value;
if (!year || !month) {
customPopups.showAlert('조회 기간을 선택해주세요.');
return;
}
// API 수수료 테이블 렌더링
const apiTableBody = document.getElementById('apiTableBody');
apiTableBody.innerHTML = '';
let apiTotal1 = 0;
let apiTotal2 = 0;
let apiCount1 = 0;
let apiCount2 = 0;
sampleData.apiCommissions.forEach((item, index) => {
if (index === 0) {
apiTableBody.innerHTML += `
<tr>
<td rowspan="${sampleData.apiCommissions.length}" class="text-center">API<br/>수수료</td>
<td class="text-left">${item.name}</td>
<td class="text-right">${formatNumber(item.count1)}</td>
<td class="text-right">${formatNumber(item.fee1)}</td>
<td class="text-right">${formatNumber(item.min1)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount1)}</span></td>
<td class="text-right"><strong style="color: #007bff;">${formatNumber(item.count2)}</strong></td>
<td class="text-right">${formatNumber(item.fee2)}</td>
<td class="text-right">${formatNumber(item.min2)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount2)}</span></td>
<td>${item.reason}</td>
</tr>
`;
} else {
apiTableBody.innerHTML += `
<tr>
<td class="text-left">${item.name}</td>
<td class="text-right">${formatNumber(item.count1)}</td>
<td class="text-right">${formatNumber(item.fee1)}</td>
<td class="text-right">${formatNumber(item.min1)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount1)}</span></td>
<td class="text-right"><strong style="color: #007bff;">${formatNumber(item.count2)}</strong></td>
<td class="text-right">${formatNumber(item.fee2)}</td>
<td class="text-right">${formatNumber(item.min2)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount2)}</span></td>
<td>${item.reason}</td>
</tr>
`;
}
apiTotal1 += item.amount1;
apiTotal2 += item.amount2;
apiCount1 += item.count1;
apiCount2 += item.count2;
});
// API 소계
apiTableBody.innerHTML += `
// API 소계
apiTableBody.innerHTML += `
<tr>
<td colspan="2" class="text-center">${year}년 ${month}월 API 수수료 소계</td>
<td class="text-right">${formatNumber(apiCount1)}</td>
@@ -339,66 +305,67 @@
</tr>
`;
// 판매 수수료 테이블 렌더링
const saleTableBody = document.getElementById('saleTableBody');
saleTableBody.innerHTML = '';
// 판매 수수료 테이블 렌더링
const saleTableBody = document.getElementById('saleTableBody');
saleTableBody.innerHTML = '';
let saleTotal1 = 0;
let saleTotal2 = 0;
let saleCount1 = 0;
let saleCount2 = 0;
let saleSalesAmount = 0;
let saleTotal1 = 0;
let saleTotal2 = 0;
let saleCount1 = 0;
let saleCount2 = 0;
let saleSalesAmount = 0;
sampleData.saleCommissions.forEach((item, index) => {
if (index === 0) {
saleTableBody.innerHTML += `
saleCommissions.forEach((item, index) => {
const isPercentageFee = item.paymentBaseName === '금액';
if (index === 0) {
saleTableBody.innerHTML += `
<tr>
<td rowspan="${sampleData.saleCommissions.length}" class="text-center">판매<br/>수수료</td>
<td class="text-left">${item.name}</td>
<td>${item.type}</td>
<td>${item.base}</td>
<td>${item.division}</td>
<td class="text-right">${item.salesAmount > 0 ? formatNumber(item.salesAmount) : ''}</td>
<td class="text-right">${item.base === '금액' ? (item.fee1 * 100) + '%' : formatNumber(item.fee1)}</td>
<td class="text-right">${formatNumber(item.count1)}</td>
<td class="text-right">${formatNumber(item.min1)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount1)}</span></td>
<td class="text-right">${item.base === '금액' ? (item.fee2 * 100) + '%' : formatNumber(item.fee2)}</td>
<td class="text-right">${formatNumber(item.count2)}</td>
<td class="text-right">${formatNumber(item.min2)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount2)}</span></td>
<td>${item.reason}</td>
<td rowspan="${saleCommissions.length}" class="text-center">판매<br/>수수료</td>
<td class="text-left">${item.paymentTargetName}</td>
<td>${item.detailFeeTypeName || ''}</td>
<td>${item.paymentBaseName || ''}</td>
<td>${item.valueDivisionName || ''}</td>
<td class="text-right">${item.totalValue ? formatNumber(item.totalValue) : ''}</td>
<td class="text-right">${isPercentageFee ? (parseFloat(item.value || 0) * 100) + '%' : formatNumber(item.value || 0)}</td>
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum || 0)}</span></td>
<td class="text-right">${isPercentageFee ? (parseFloat(item.value2 || 0) * 100) + '%' : formatNumber(item.value2 || 0)}</td>
<td class="text-right">${formatNumber(item.totalCount2 || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum2 || 0)}</span></td>
<td>${item.changeReason2 || ''}</td>
</tr>
`;
} else {
saleTableBody.innerHTML += `
} else {
saleTableBody.innerHTML += `
<tr>
<td class="text-left">${item.name}</td>
<td>${item.type}</td>
<td>${item.base}</td>
<td>${item.division}</td>
<td class="text-right">${item.salesAmount > 0 ? formatNumber(item.salesAmount) : ''}</td>
<td class="text-right">${item.base === '금액' ? (item.fee1 * 100) + '%' : formatNumber(item.fee1)}</td>
<td class="text-right">${formatNumber(item.count1)}</td>
<td class="text-right">${formatNumber(item.min1)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount1)}</span></td>
<td class="text-right">${item.base === '금액' ? (item.fee2 * 100) + '%' : formatNumber(item.fee2)}</td>
<td class="text-right">${formatNumber(item.count2)}</td>
<td class="text-right">${formatNumber(item.min2)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.amount2)}</span></td>
<td>${item.reason}</td>
<td class="text-left">${item.paymentTargetName}</td>
<td>${item.detailFeeTypeName || ''}</td>
<td>${item.paymentBaseName || ''}</td>
<td>${item.valueDivisionName || ''}</td>
<td class="text-right">${item.totalValue ? formatNumber(item.totalValue) : ''}</td>
<td class="text-right">${isPercentageFee ? (parseFloat(item.value || 0) * 100) + '%' : formatNumber(item.value || 0)}</td>
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum || 0)}</span></td>
<td class="text-right">${isPercentageFee ? (parseFloat(item.value2 || 0) * 100) + '%' : formatNumber(item.value2 || 0)}</td>
<td class="text-right">${formatNumber(item.totalCount2 || 0)}</td>
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
<td class="text-right"><span style="color: #8b0000;">${formatNumber(item.sum2 || 0)}</span></td>
<td>${item.changeReason2 || ''}</td>
</tr>
`;
}
saleTotal1 += item.amount1;
saleTotal2 += item.amount2;
saleCount1 += item.count1;
saleCount2 += item.count2;
saleSalesAmount += item.salesAmount;
});
}
saleTotal1 += parseFloat(item.sum || 0);
saleTotal2 += parseFloat(item.sum2 || 0);
saleCount1 += parseInt(item.totalCount || 0);
saleCount2 += parseInt(item.totalCount2 || 0);
saleSalesAmount += parseFloat(item.totalValue || 0);
});
// 판매 소계
saleTableBody.innerHTML += `
// 판매 소계
saleTableBody.innerHTML += `
<tr>
<td colspan="5" class="text-center">${year}년 ${month}월 판매 수수료 소계</td>
<td class="text-right">${formatNumber(saleSalesAmount)}</td>
@@ -414,54 +381,33 @@
</tr>
`;
// 합계 업데이트
document.getElementById('totalTitle').textContent = `${year}년 ${month}월 합계`;
document.getElementById('totalSalesAmount1').textContent = formatNumber(saleSalesAmount);
document.getElementById('totalCount1').textContent = formatNumber(apiCount1 + saleCount1);
document.getElementById('totalAmount1').textContent = formatNumber(apiTotal1 + saleTotal1);
document.getElementById('totalSalesAmount2').textContent = formatNumber(saleSalesAmount);
document.getElementById('totalCount2').textContent = formatNumber(apiCount2 + saleCount2);
document.getElementById('totalAmount2').textContent = formatNumber(apiTotal2 + saleTotal2);
// 합계 업데이트
document.getElementById('totalTitle').textContent = `${year}년 ${month}월 합계`;
document.getElementById('totalSalesAmount1').textContent = formatNumber(saleSalesAmount);
document.getElementById('totalCount1').textContent = formatNumber(apiCount1 + saleCount1);
document.getElementById('totalAmount1').textContent = formatNumber(apiTotal1 + saleTotal1);
document.getElementById('totalSalesAmount2').textContent = formatNumber(saleSalesAmount);
document.getElementById('totalCount2').textContent = formatNumber(apiCount2 + saleCount2);
document.getElementById('totalAmount2').textContent = formatNumber(apiTotal2 + saleTotal2);
// 출력 버튼 표시
document.getElementById('printBtn').style.display = 'inline-block';
}
// 출력 버튼 표시
document.getElementById('printBtn').style.display = 'inline-block';
}
function printCommission() {
const year = document.getElementById('forYear').value;
const month = document.getElementById('forMonth').value;
function printCommission() {
const year = document.getElementById('forYear').value;
const month = document.getElementById('forMonth').value;
if (!year || !month) {
customPopups.showAlert('조회 기간을 선택해주세요.');
return;
}
if (!year || !month) {
customPopups.showAlert('조회 기간을 선택해주세요.');
return;
}
// 별도 창으로 청구서 출력 페이지 열기
const printUrl = '/commission/print/' + year + '/' + month;
window.open(printUrl, '_blank', 'width=800,height=900,scrollbars=yes,resizable=yes');
}
function downloadExcel() {
customPopups.showAlert('엑셀 다운로드 기능 (구현 예정)');
}
// 페이지 로드 시 초기 데이터 로드
window.onload = function() {
loadData();
};
</script>
<style>
.glyphicon-search::before {
content: "🔍";
}
@media print {
.searchBox,
.searchInfo {
display: none !important;
}
}
</style>
// 별도 창으로 청구서 출력 페이지 열기
const printUrl = '/commission/print/' + year + '/' + month;
window.open(printUrl, '_blank', 'width=800,height=900,scrollbars=yes,resizable=yes');
}
</script>
</th:block>
</body>
</html>
@@ -3,62 +3,63 @@
<head>
<meta charset="utf-8">
<title>수수료 청구서</title>
<link rel="stylesheet" th:href="@{/content/css/vendor.css}">
<style>
html,body{font-size:12px;}
body{width:600px; margin:90px; font-family: 'Noto Sans KR', -apple-system, sans-serif;}
table{border-collapse: collapse;}
table th, td{padding:5px 10px;}
table tr{font-size:12px;}
.info-table{ border-top: 10px solid gray; width: 100%; border-bottom: 2px solid #333;}
.info-table th{text-align:left;}
.commission-table{width:100%;}
.commission-table th,.commission-table td{border:1px solid #999 !important}
.commission-table td{text-align:right}
.bg_ygreen{background-color:aquamarine; text-align:center}
.bg_skyBlue{background-color:skyblue; text-align:center}
.bg_yellow{background-color:yellow; text-align:center}
<!-- <link rel="stylesheet" th:href="@{/content/css/vendor.css}">-->
<!-- <link rel="stylesheet" th:href="@{/css/main.css}">-->
<style>
html,body{font-size:12px;}
body{width:600px; margin:90px}
table{border-collapse: collapse;}
table th, td{padding:5px 10px;}
table tr{font-size:12px;}
.info-table{ border-top: 10px solid gray; width: 100%; border-bottom: 2px solid #333;}
.info-table th{text-align:left;}
.commission-table{width:100%;}
.commission-table th,.commission-table td{border:1px solid #999 !important}
.commission-table td{text-align:right}
.bg_ygreen{background-color:aquamarine; text-align:center}
.bg_skyBlue{background-color:skyblue; text-align:center}
.bg_yellow{background-color:yellow; text-align:center}
DIV { position: relative; }
DIV { position: relative; }
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5a67d8;
}
.btn-primary:hover {
background: #5a67d8;
}
@media print {
@page {
size: auto;
margin: 0 -0cm;
}
html {
margin:0 0cm;
}
#printButton, #backButton {
display: none !important;
}
}
</style>
@media print {
@page {
size: auto;
margin: 0 -0cm;
}
html {
margin: 0 0cm;
}
.control {
display: none !important;
}
}
</style>
</head>
<body>
<button id="backButton" class="btn btn-primary" style="margin-right: 10px;" onclick="history.back()">뒤로가기</button>
<input id="printButton" type="button" class="btn btn-primary" value="청구서 인쇄" onclick="window.print()"/>
<body class="commission-print-page">
<div class="control">
<input id="printButton" type="button" class="btn btn-primary" value="청구서 인쇄" onclick="window.print()"/>
</div>
<div id="PrintDIV">
<h1 style="text-align:center">
<img style="width:300px;" th:src="@{/img/portal/logo.jpg}" alt="광주은행 오픈뱅킹" />
<img style="height:30px;" th:src="@{/img/logo/logo.png}" alt="광주은행 오픈뱅킹" />
</h1>
<p style="text-align:center">우61470 광주광역시 동구 제봉로 225 전화 (062)239-6722 FAX (062)239-6719 오픈뱅크 플랫폼 담당자</p>
@@ -160,71 +161,6 @@
</tr>
</th:block>
</th:block>
<!-- 샘플 데이터 (commission이 null인 경우) -->
<th:block th:if="${commission == null}">
<tr>
<td style="text-align:left">계좌잔액조회</td>
<td></td>
<td>20,543</td>
<td>₩50</td>
<td>₩1,027,150</td>
</tr>
<tr>
<td style="text-align:left">거래내역조회</td>
<td></td>
<td>11,876</td>
<td>₩80</td>
<td>₩950,080</td>
</tr>
<tr>
<td style="text-align:left">송금 API</td>
<td></td>
<td>4,892</td>
<td>₩200</td>
<td>₩978,400</td>
</tr>
<tr>
<td style="text-align:left">본인인증 API</td>
<td></td>
<td>2,341</td>
<td>₩150</td>
<td>₩351,150</td>
</tr>
<tr>
<th class="bg_skyBlue" colspan="4">소계</th>
<td class="bg_skyBlue">₩3,306,780</td>
</tr>
<tr>
<td style="text-align:left">개인대출 상품 A</td>
<td>₩1,050,000,000</td>
<td>55</td>
<td>₩5,000</td>
<td>₩275,000</td>
</tr>
<tr>
<td style="text-align:left">기업대출 상품 B</td>
<td>₩1,680,000,000</td>
<td>21</td>
<td>₩8,000</td>
<td>₩168,000</td>
</tr>
<tr>
<td style="text-align:left">소상공인 대출 C</td>
<td>₩450,000,000</td>
<td>30</td>
<td>₩3,000</td>
<td>₩90,000</td>
</tr>
<tr>
<th class="bg_skyBlue" colspan="4">소계</th>
<td class="bg_skyBlue">₩533,000</td>
</tr>
<tr>
<th class="bg_yellow" colspan="4">합계</th>
<td class="bg_yellow">₩3,839,780</td>
</tr>
</th:block>
</tbody>
</table>
@@ -30,7 +30,7 @@
<input type="text"
th:field="*{searchWrd}"
placeholder="질문 또는 답변 내용으로 검색">
<button type="button" onclick="fn_search_article()">
<button type="button" class="btn btn-primary" onclick="fn_search_article()">
<i class="fas fa-search"></i>
<span>검색</span>
</button>
@@ -30,7 +30,7 @@
name="searchWrd"
th:value="${search.searchWrd}"
placeholder="제목 또는 내용으로 검색">
<button type="button" onclick="fn_search_inquiry()">
<button type="button" class="btn btn-primary" onclick="fn_search_inquiry()">
<i class="fas fa-search"></i>
<span>검색</span>
</button>
@@ -92,7 +92,7 @@
<!-- New Inquiry Button -->
<div class="inquiry-actions">
<a th:href="@{/inquiry/new}" class="action-btn-new">
<a th:href="@{/inquiry/new}" class="btn btn-primary">
<i class="fas fa-pen"></i>
<span>질문하기</span>
</a>
@@ -28,7 +28,7 @@
name="searchSubjectOrDetail"
th:value="${search.searchSubjectOrDetail}"
placeholder="제목 또는 내용으로 검색">
<button type="button" onclick="fn_search_notice()">
<button type="button" class="btn btn-primary" onclick="fn_search_notice()">
<i class="fas fa-search"></i>
<span>검색</span>
</button>
@@ -1,6 +1,6 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_base_layout}">
<body>
<section layout:fragment="contentFragment">
@@ -16,10 +16,10 @@
<div class="apikey-actions">
<button sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"
type="button"
class="btn-create-app"
class="btn btn-primary"
id="requestApiKey">
<span class="btn-icon"></span>
앱 생성
<i class="fas fa-plus"></i>
<span>앱 생성하기</span>
</button>
</div>
</div>
@@ -129,10 +129,10 @@
<p>새로운 앱을 생성하여 API를 사용해보세요.</p>
<button sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"
type="button"
class="btn-create-app-large"
class="btn btn-primary"
id="requestApiKeyEmpty">
<span class="btn-icon"></span>
첫 앱 생성하기
<i class="fas fa-plus"></i>
<span>첫 앱 생성하기</span>
</button>
</div>
@@ -180,10 +180,10 @@
<!-- Action Buttons -->
<div class="form-actions">
<a th:href="@{/myapikey/modify/cancel(clientId=${apiKeyModification.clientId})}" class="btn-cancel">
<a th:href="@{/myapikey/modify/cancel(clientId=${apiKeyModification.clientId})}" class="btn btn-cancel">
취소
</a>
<button type="submit" class="btn-primary">
<button type="submit" class="btn btn-primary">
다음 단계
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="9 18 15 12 9 6"></polyline>
@@ -374,4 +374,4 @@
</th:block>
</body>
</html>
</html>
@@ -129,11 +129,11 @@
<!-- Form Actions -->
<div class="form-actions">
<!-- Save and go back button -->
<button type="submit" formaction="/myapikey/modify/step2/save" class="btn-secondary" id="btnPrevStep">
<button type="submit" formaction="/myapikey/modify/step2/save" class="btn btn-secondary" id="btnPrevStep">
<span class="icon"></span>
이전 단계
</button>
<button type="submit" class="btn-primary" id="btnNext">
<button type="submit" class="btn btn-primary" id="btnNext">
저장
<span class="icon"></span>
</button>
@@ -53,11 +53,11 @@
<!-- Action Buttons -->
<div class="result-actions">
<a th:href="@{/myapikey}" class="btn-secondary">
<a th:href="@{/myapikey}" class="btn btn-secondary">
<span class="icon">📋</span>
API Key 목록으로
</a>
<a th:href="@{/myapikey/api_key_request/history}" class="btn-primary">
<a th:href="@{/myapikey/api_key_request/history}" class="btn btn-primary">
<span class="icon">📄</span>
요청 내역 확인
</a>
@@ -79,7 +79,7 @@
</p>
</div>
<div class="result-actions">
<a th:href="@{/myapikey}" class="btn-primary">
<a th:href="@{/myapikey}" class="btn btn-primary">
목록으로 돌아가기
</a>
</div>
@@ -149,4 +149,4 @@
</th:block>
</body>
</html>
</html>
@@ -177,11 +177,11 @@
<!-- Form Actions -->
<div class="form-actions">
<a href="/myapikey" class="btn-secondary" id="btnCancel">
<a href="/myapikey" class="btn btn-secondary" id="btnCancel">
<span class="icon"></span>
취소
</a>
<button type="submit" class="btn-primary">
<button type="submit" class="btn btn-primary">
다음 단계
<span class="icon"></span>
</button>
@@ -115,11 +115,11 @@
<!-- Form Actions -->
<div class="form-actions">
<button type="button" id="btnPrevStep" class="btn-secondary">
<button type="button" id="btnPrevStep" class="btn btn-secondary">
<span class="icon"></span>
이전 단계
</button>
<button type="submit" class="btn-primary">
<button type="submit" class="btn btn-primary">
저장
<span class="icon"></span>
</button>
@@ -53,7 +53,7 @@
<!-- Action Buttons -->
<div class="result-actions">
<a href="/myapikey" class="btn-secondary">
<a href="/myapikey" class="btn btn-secondary">
<span class="icon">📋</span>
API Key 목록으로
</a>
@@ -75,10 +75,10 @@
</p>
</div>
<div class="result-actions">
<a href="/myapikey/register/step1" class="btn-secondary">
<a href="/myapikey/register/step1" class="btn btn-secondary">
다시 시도
</a>
<a href="/myapikey" class="btn-primary">
<a href="/myapikey" class="btn btn-primary">
목록으로
</a>
</div>
@@ -147,14 +147,14 @@
<div class="detail-actions">
<button type="button"
sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"
class="btn-cancel"
class="btn btn-secondary"
th:if="${appRequest.approval != null and appRequest.approval.approvalStatus != null and
(appRequest.approval.approvalStatus.toString() == 'PENDING' or appRequest.approval.approvalStatus.toString() == 'REQUESTED')}"
th:data-request-id="${appRequest.id}"
onclick="cancelRequestById(this)">
신청 취소
</button>
<a th:href="@{/myapikey}" class="btn-secondary">
<a th:href="@{/myapikey}" class="btn btn-primary">
목록으로
</a>
</div>
@@ -49,7 +49,7 @@
maxlength="4"
disabled="disabled">
</div>
<button type="button" class="org-btn org-btn-secondary change_mobile_phone" id="changePhoneBtn">변경</button>
<button type="button" class="btn btn-secondary change_mobile_phone" id="changePhoneBtn">변경</button>
</div>
</div>
<div class="org-form-group" id="newPhoneNumberContainer" style="display: none;">
@@ -75,7 +75,7 @@
maxlength="4" pattern="\d*" inputmode="numeric" placeholder="뒷자리"/>
<input type="hidden" value="" name="mobileNumber" id="mobileNumber">
</div>
<button type="button" class="org-btn org-btn-primary btn_auth">
<button type="button" class="btn btn-primary btn_auth">
인증번호 받기
</button>
</div>
@@ -91,7 +91,7 @@
placeholder="SMS 인증번호 6자리">
<span class="org-timer" id="certify_time">03:00</span>
</div>
<button type="button" class="org-btn org-btn-primary btn_verify_auth">
<button type="button" class="btn btn-primary btn_verify_auth">
인증번호 확인
</button>
</div>
@@ -178,20 +178,20 @@
</div>
<!-- Action Buttons -->
<div class="detail-actions">
<div class="form-actions">
<a sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"
class="btn-action btn-primary"
class="btn btn-primary"
th:href="@{/myapikey/modify/step1(clientId=${apiKey.clientid})}">
수정
</a>
<button type="button"
sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"
class="btn-action btn-danger"
class="btn btn-danger"
th:data-client-id="${apiKey.clientid}"
onclick="deleteApiKeyFromButton(this)">
인증키 삭제
</button>
<a th:href="@{/myapikey}" class="btn-secondary">
<a th:href="@{/myapikey}" class="btn btn-secondary">
목록으로
</a>
</div>
@@ -58,8 +58,8 @@
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" id="cancelButton" th:onclick="|location.href='@{/mypage}'|">취소</button>
<button type="button" class="org-btn org-btn-primary" id="submitButton">법인회원 전환</button>
<button type="button" class="btn btn-secondary" id="cancelButton" th:onclick="|location.href='@{/mypage}'|">취소</button>
<button type="button" class="btn btn-primary" id="submitButton">법인회원 전환</button>
</div>
</form>
</div>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<head>
<title>비밀번호 변경</title>
</head>
@@ -51,8 +51,8 @@
</div>
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" onclick="history.back()">취소</button>
<button type="submit" class="org-btn org-btn-primary">변경</button>
<button type="button" class="btn btn-secondary" onclick="history.back()">취소</button>
<button type="submit" class="btn btn-primary">변경</button>
</div>
</form>
</div>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -31,8 +31,8 @@
</div>
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="submit" class="org-btn org-btn-primary">확인</button>
<button type="button" class="btn btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="submit" class="btn btn-primary">확인</button>
</div>
</form>
</div>
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -214,8 +214,8 @@
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="org-btn org-btn-primary">수정 적용</button>
<button type="button" class="btn btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="btn btn-primary">수정 적용</button>
</div>
</form>
@@ -573,7 +573,7 @@
});
// 수정 버튼 이벤트
const submitButton = document.querySelector('.org-btn-primary:not(.btn_add2)');
const submitButton = document.querySelector('.btn-primary:not(.btn_add2)');
if (submitButton) {
submitButton.addEventListener('click', function(e) {
e.preventDefault();
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -30,8 +30,8 @@
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="org-btn org-btn-primary submit-btn">수정 적용</button>
<button type="button" class="btn btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="btn btn-primary submit-btn">수정 적용</button>
</div>
</form>
@@ -64,7 +64,7 @@
const form = document.getElementById('updateForm');
// 수정 버튼 이벤트
const submitButton = document.querySelector('.org-btn-primary.submit-btn');
const submitButton = document.querySelector('.btn-primary.submit-btn');
if (submitButton) {
submitButton.addEventListener('click', function (e) {
e.preventDefault();
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -22,15 +22,15 @@
<!-- Corporate Transfer Button -->
<div class="org-info-notice" style="margin-top: 32px;">
<button type="button" class="org-btn org-btn-secondary btn_business" style="width: 100%;">
<button type="button" class="btn btn-secondary btn_business" style="width: 100%;">
법인회원 전환
</button>
</div>
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="org-btn org-btn-primary submit-btn">수정</button>
<button type="button" class="btn btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="btn btn-primary submit-btn">수정</button>
</div>
</form>
@@ -65,7 +65,7 @@
const form = document.getElementById('updateForm');
// 수정 버튼 이벤트
const submitButton = document.querySelector('.org-btn-primary.submit-btn');
const submitButton = document.querySelector('.btn-primary.submit-btn');
if (submitButton) {
submitButton.addEventListener('click', function (e) {
e.preventDefault();
@@ -27,7 +27,7 @@
<input type="hidden" id="loginId" name="loginId" th:value="${loginId}">
<input type="hidden" name="registrationType" th:value="${registrationType}"/>
<input type="hidden" id="registrationScenario" name="registrationScenario" value="new"/>
<button type="button" class="org-btn org-btn-check btn_check_email"
<button type="button" class="btn org-btn-check btn_check_email"
th:classappend="${isInvited ? 'hidden' : ''}">
중복체크
</button>
@@ -40,7 +40,7 @@
th:placeholder="#{portal.Register.phone2}">
</div>
<input type="hidden" th:field="*{mobileNumber}" id="mobileNumber">
<button type="button" class="org-btn org-btn-check btn_auth">
<button type="button" class="btn org-btn-check btn_auth">
인증번호 받기
</button>
<div id="mobile-validation" class="org-validation-message"></div>
@@ -59,7 +59,7 @@
inputmode="numeric" class="org-form-input" th:placeholder="#{ncrdRegister.validate.authNumber}" required>
<span class="org-timer" id="certify_time">03:00</span>
</div>
<button type="button" class="org-btn org-btn-check btn_verify_auth">
<button type="button" class="btn org-btn-check btn_verify_auth">
인증번호 확인
</button>
<div id="authNumber-validation" class="org-validation-message"></div>
@@ -16,7 +16,7 @@
<input type="text" id="domain" class="org-form-input"
placeholder="도메인">
</div>
<button type="button" class="org-btn org-btn-check btn_check_email">
<button type="button" class="btn org-btn-check btn_check_email">
중복체크
</button>
</div>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -55,8 +55,8 @@
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" id="cancelButton">취소</button>
<button type="button" class="org-btn org-btn-primary btn_register">가입신청</button>
<button type="button" class="btn btn-secondary" id="cancelButton">취소</button>
<button type="button" class="btn btn-primary btn_register">가입신청</button>
</div>
</form>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_signup_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="title">
<div class="org-page-title-banner">
@@ -60,8 +60,8 @@
<!-- Action Buttons -->
<div class="org-action-buttons">
<button type="button" class="org-btn org-btn-secondary" id="cancelButton">취소</button>
<button type="button" class="org-btn org-btn-primary btn_register">가입신청</button>
<button type="button" class="btn btn-secondary" id="cancelButton">취소</button>
<button type="button" class="btn btn-primary btn_register">가입신청</button>
</div>
</form>
@@ -101,7 +101,7 @@
<!-- Action Buttons -->
<div class="detail-actions">
<a th:href="@{/users}" class="btn-secondary">
<a th:href="@{/users}" class="btn btn-secondary">
<i class="fas fa-list"></i> 목록으로
</a>
</div>
@@ -13,9 +13,9 @@
<h2>이용자 목록</h2>
</div>
<div class="user-management-actions">
<button type="button" class="btn-create-user" id="addUserBtn">
<span class="btn-icon"></span>
이용자 추가
<button type="button" class="btn btn-primary" id="addUserBtn">
<i class="fas fa-plus"></i>
<span>이용자 추가</span>
</button>
</div>
</div>
@@ -72,25 +72,25 @@
<!-- Action Buttons -->
<div class="user-action-buttons" th:if="${user.roleCode != null and user.id != currentUserId}">
<button type="button" class="btn-action btn-sm btn-secondary inactivate_user"
<button type="button" class="btn btn-sm btn-secondary inactivate_user"
th:if="${user.userStatus.toString() == 'ACTIVE'}"
th:data-user-id="${user.id}"
th:data-user-name="${user.maskedUserName}">
비활성화
</button>
<button type="button" class="btn-action btn-sm btn-primary activate_user"
<button type="button" class="btn btn-sm btn-primary activate_user"
th:if="${user.userStatus.toString() != 'ACTIVE'}"
th:data-user-id="${user.id}"
th:data-user-name="${user.maskedUserName}">
활성화
</button>
<button type="button" class="btn-action btn-sm btn-danger cancel_invitation"
<button type="button" class="btn btn-sm btn-secondary cancel_invitation"
th:if="${user.userStatus.toString() == 'PENDING'}"
th:data-user-id="${user.id}"
th:data-user-email="${user.maskedEmailAddr}">
초대취소
</button>
<button type="button" class="btn-action btn-sm btn-warning assign_manager"
<button type="button" class="btn btn-sm btn-warning assign_manager"
th:if="${user.userStatus.toString() == 'ACTIVE' && user.roleCode.toString() == 'ROLE_CORP_USER'}"
th:data-user-id="${user.id}"
th:data-user-name="${user.maskedUserName}"
@@ -120,7 +120,7 @@
</div>
<div class="col-actions">
<div class="user-action-buttons">
<button type="button" class="btn-action btn-sm btn-danger cancel_invitation"
<button type="button" class="btn btn-sm btn-secondary cancel_invitation"
th:data-user-id="${user.id}"
th:data-user-email="${user.maskedEmailAddr}">
초대취소
@@ -136,9 +136,9 @@
<div class="empty-icon">👥</div>
<h3>등록된 이용자가 없습니다</h3>
<p>새로운 이용자를 추가하여 시작하세요.</p>
<button type="button" class="btn-create-user-large" id="addUserBtnEmpty">
<span class="btn-icon"></span>
첫 이용자 추가하기
<button type="button" class="btn btn-primary" id="addUserBtnEmpty">
<i class="fas fa-plus"></i>
<span>첫 이용자 추가하기</span>
</button>
</div>
@@ -8,9 +8,9 @@
<div class="footer-left">
<img src="/img/logo/logo.png" alt="광주은행" class="footer-logo">
<div class="footer-links">
<a href="#" class="footer-link">이용약관</a>
<a th:href="@{/agreements/terms}" class="footer-link">이용약관</a>
<span class="footer-separator"></span>
<a href="#" class="footer-link">개인정보처리방침</a>
<a th:href="@{/agreements/terms(tab=privacy)}" class="footer-link">개인정보처리방침</a>
</div>
<p class="footer-copyright">Copyright 2025 Kwangju Bank. All Rights Reserved.</p>
</div>
@@ -62,7 +62,7 @@
</li>
<li sec:authorize="hasRole('ROLE_APP')">
<a th:href="@{/myapikey}"><i class="fas fa-key"></i>인증 키 관리</a>
<a th:href="@{/commission/manage}"><i class="fas fa-key"></i>과금 관리</a>
<a th:href="@{/commission/manage}"><i class="fas fa-money-bill"></i>과금 관리</a>
</li>
<li><a th:href="@{/mypage}"><i class="fas fa-user-circle"></i>내 정보 관리</a></li>
<li><a th:href="@{/change_password}"><i class="fas fa-lock"></i>비밀번호 변경</a></li>
@@ -148,11 +148,6 @@
<i class="fas fa-key"></i> 인증 키 관리
</a>
</li>
<!-- <li sec:authorize="hasRole('ROLE_API_KEY_REQUEST_VIEW')">-->
<!-- <a th:href="@{/myapikey/api_key_request/history}" class="drawer-link">-->
<!-- <i class="fas fa-list"></i> 인증키 신청 목록-->
<!-- </a>-->
<!-- </li>-->
<li sec:authorize="isAuthenticated()">
<a th:href="@{/mypage}" class="drawer-link">
<i class="fas fa-user-circle"></i> 내 정보 관리
@@ -1,74 +1,106 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/kjbank_base_layout}">
layout:decorate="~{layout/kjbank_title_layout}">
<body>
<section layout:fragment="contentFragment" class="content">
<div class="content_wrap">
<div class="sub_title2">
<h2 class="title" th:classappend="${isTermsOfUse ? 'add3' : 'add4'}"
th:text="${agreementTitle}">이용약관</h2>
</div>
<div class="inner cs2">
<div class="tab-wrap">
<div class="tabs">
<ul class="tab_nav tab_bt">
<li th:class="${isTermsOfUse ? 'active' : ''}">
<a th:href="@{/agreements/terms(tab='terms')}">이용약관</a>
</li>
<li th:class="${isPrivacyPolicy ? 'active' : ''}">
<a th:href="@{/agreements/terms(tab='privacy')}">개인정보처리방침</a>
</li>
</ul>
<div class="tab active" th:id="${isTermsOfUse ? 'tab1' : 'tab2'}">
<div class="form_type">
<div class="info1 ts_top">
<div class="info_line ts_left">
<div class="info_box1 info_add3 info_top">
<span class="input">
<form id="agreementForm" th:action="@{/agreements/terms}" method="get">
<input type="hidden" name="tab"
th:value="${currentTab}">
<div class="custom_select" id="agreement_select">
<div class="select_selected">
시행일자 : <span th:text="${#temporals.format(selectedAgreement.publishedOn, 'yyyy.MM.dd')}"></span>
</div>
<ul class="common_selecttype select_items select_hide">
<li th:each="agreement : ${agreementsList}"
th:data-id="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd')}"
th:text="'시행일자 : ' + ${#temporals.format(agreement.publishedOn, 'yyyy.MM.dd')}"
th:class="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd') == selectedDate ? 'selected' : ''}">
</li>
</ul>
</div>
<input type="hidden" name="publishedOn" id="publishedOnInput">
</form>
</span>
</div>
</div>
</div>
</div>
<div class="terms_contents m_termst" th:utext="${selectedAgreement.contents}"
style="white-space: pre-wrap; word-wrap: break-word;">
</div>
</div>
</div>
</div>
</div>
<section layout:fragment="title">
<div class="org-page-title-banner">
<img th:src="@{/img/user_register_title.png}" class="title-image">
<h1 th:text="${agreementTitle}">비밀번호 변경</h1>
</div>
</section>
<section layout:fragment="contentFragment">
<div class="org-info-notice">
<ul>
<li>광주은행 서비스 이용약관 및 개인정보처리방침을 확인하실 수 있습니다.</li>
</ul>
</div>
<div class="terms-container">
<!-- Tab Navigation -->
<div class="terms-tabs">
<a th:href="@{/agreements/terms(tab='terms')}"
class="tab-link"
th:classappend="${isTermsOfUse ? 'active' : ''}">
<i class="fas fa-file-alt"></i>
이용약관
</a>
<a th:href="@{/agreements/terms(tab='privacy')}"
class="tab-link"
th:classappend="${isPrivacyPolicy ? 'active' : ''}">
<i class="fas fa-shield-alt"></i>
개인정보처리방침
</a>
</div>
<!-- Version Selector -->
<div class="terms-selector">
<form id="agreementForm" th:action="@{/agreements/terms}" method="get">
<input type="hidden" name="tab" th:value="${currentTab}">
<div class="custom-select" id="agreement_select">
<div class="select-selected">
<i class="fas fa-calendar-alt"></i>
시행일자 : <span th:text="${#temporals.format(selectedAgreement.publishedOn, 'yyyy.MM.dd')}"></span>
<i class="fas fa-chevron-down"></i>
</div>
<ul class="select-items select-hide">
<li th:each="agreement : ${agreementsList}"
th:data-id="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd')}"
th:text="'시행일자 : ' + ${#temporals.format(agreement.publishedOn, 'yyyy.MM.dd')}"
th:class="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd') == selectedDate ? 'selected' : ''}">
</li>
</ul>
</div>
<input type="hidden" name="publishedOn" id="publishedOnInput">
</form>
</div>
<!-- Terms Content -->
<div class="terms-content">
<div class="content-body" th:utext="${selectedAgreement.contents}"></div>
</div>
</div>
</section>
<script layout:fragment="contentScript">
document.addEventListener('DOMContentLoaded', function () {
const selects = document.getElementById('agreement_select');
const form = document.getElementById('agreementForm');
const publishedOnInput = document.getElementById('publishedOnInput');
document.addEventListener('DOMContentLoaded', function() {
const customSelect = document.getElementById('agreement_select');
const selectSelected = customSelect.querySelector('.select-selected');
const selectItems = customSelect.querySelector('.select-items');
const form = document.getElementById('agreementForm');
const publishedOnInput = document.getElementById('publishedOnInput');
createCustomSelect(selects, {
onSelect: (item) => {
publishedOnInput.value = item;
form.submit();
}
});
// Toggle dropdown on click
selectSelected.addEventListener('click', function(e) {
e.stopPropagation();
selectItems.classList.toggle('select-hide');
selectSelected.classList.toggle('select-arrow-active');
});
// Handle option selection
const options = selectItems.querySelectorAll('li');
options.forEach(option => {
option.addEventListener('click', function() {
const selectedDate = this.getAttribute('data-id');
publishedOnInput.value = selectedDate;
// Update selected state
options.forEach(opt => opt.classList.remove('selected'));
this.classList.add('selected');
// Close dropdown
selectItems.classList.add('select-hide');
selectSelected.classList.remove('select-arrow-active');
// Submit form
form.submit();
});
});
// Close dropdown when clicking outside
document.addEventListener('click', function() {
selectItems.classList.add('select-hide');
selectSelected.classList.remove('select-arrow-active');
});
});
</script>
</body>
</html>