34 Commits

Author SHA1 Message Date
8cdbfd3cbf 사용하지 않는 부분에 대한 출력 삭제 2026-02-20 16:20:26 +09:00
2884c209d2 만료 카드에 대해 입장처리가 가능하도록 수정, 만료 카드의 경우 경고문구가 뜨도록 수정. 2026-02-20 16:18:39 +09:00
693625a0bc 멤버 목록 정렬 방식 수정, 관리자 권한 체크 부분 수정 2026-02-20 16:18:16 +09:00
b2979f0211 관리자 수정 2026-02-20 15:57:45 +09:00
fdcf58cd6e Feat: 만료 상태 자동 복구 - VIP 입장처리 시 상태를 정상으로 변경
- 입장처리 시 기존 상태가 '만료'라면 '정상'으로 자동 변경
- 로그에 상태 변경 정보 기록 (만료정상)
2026-02-20 15:55:13 +09:00
d2bcdd0dc9 Fix: VIP 카테고리 모두보기 토글 - display 속성으로 즉시 반영
- PHP에서 비활성 카테고리도 항상 렌더링하도록 continue 제거
- input과 label 모두에 inactive-cat 클래스 추가
- JavaScript에서 .inactive-cat 요소의 display를 토글하여 즉시 반영
2026-02-20 15:52:36 +09:00
f1fce78661 Fix: VIP 리스트 행 클릭 모달 - 작업 셀 제외 처리
- 작업 셀(입장처리, 수정, 재발급, 삭제 버튼) 클릭 시 모달이 나타나지 않도록 수정
- 확인 대화창에서 취소 선택 시에도 모달이 나타나지 않도록 개선
- handleRowClick() 함수 추가로 action-cell 클릭 시 이벤트 무시
2026-02-20 15:46:59 +09:00
d3d9f2e8ed 만료시 투명도 조절을 하던 부분을 색상 자체를 변경하도록 수정
만료 카드라도 입장처리 및 수정이 가능하도록 변경
2026-02-20 15:43:36 +09:00
3afec44da9 Feat: VIP 관리 시스템 개선 - 모달 구조 정리, 만료일 자동 상태 관리
- VIP 리스트 모달을 루프 내 숨겨진 TR에 통합 (Bootstrap 호환성 유지)
- X 아이콘 제거 및 액션 버튼 표시 조건 개선 (status='정상'인 경우만 표시)
- 행 높이 표준화 (60px, align-middle)
- 만료일이 오늘 이전일 경우 상태 자동 '만료' 처리 (AJAX 및 1회성 실행 모드)
- 만료일 설정 페이지 결과 테이블에 상태 변경 정보 추가
2026-02-20 15:38:38 +09:00
bd1f111e8d Fix: VIP 리스트 모달 표시 문제 해결, 카테고리 필터 페이지 리로드 제거 2026-02-20 15:05:51 +09:00
d20287fdbd Feat: VIP 리스트 페이지 UX 개선 - 만료일 스타일링, 행 클릭 모달, 경고창, 카테고리 필터 추가 2026-02-20 15:03:35 +09:00
65d874d563 Feat: VIP 만료일 설정 페이지를 독립 실행 방식으로 개선 - 직접 접근 시 UI 제공, 1회성 일괄 처리 지원 2026-02-20 14:57:27 +09:00
fc093e0908 Feat: VIP 만료일 관리 기능 추가 - 테이블에 만료일 컬럼 추가, 입장 시 자동 만료일 설정, 일괄 설정 페이지 추가 2026-02-20 14:52:06 +09:00
84d4ece13f Fix: 파일명 생성 부분의 확장자 붙임 수정. 2026-02-20 14:01:58 +09:00
bdf228e69d Merge remote-tracking branch '그누보드/master' 2026-02-20 11:42:31 +09:00
4900f86d74 이용횟수 추가 2026-02-20 11:40:43 +09:00
bff2a4ae2b Merge branch 'main' of https://git.siane.kr/firstgarden/firstgarden-web-gnu
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2026-02-20 11:40:13 +09:00
644b0103a2 Fix: 연간회원 엑셀 내보내기 기능 수정 - 버튼 경로 수정 및 연간회원 테이블 쿼리 적용 2026-02-20 09:41:29 +09:00
ef1be317e1 버전 5.6.24 수정 2026-02-03 06:25:50 +00:00
137d78ff73 영카트 관리자모드 분류출력 개선 2026-02-03 06:24:34 +00:00
0ddcda4b0c toss 모바일결제 포인트 적용시 결제 오류 수정 2026-02-02 09:37:49 +00:00
bf27af3925 영카트 shop_is_taxsave 에서 볌수 코드 오타 수정 2026-02-02 07:33:36 +00:00
607e15424d 토스결제 비회원결제가 안되는 오류 및 모바일 개인결제 취소과정 코드 수정 2026-02-02 07:18:28 +00:00
7c490448ec 메일보내기 발신자 위장 방지 및 암호화 키의 안전성 취약점 수정 2026-01-30 05:00:43 +00:00
d775d2255f [KVE-2026-0029]Stored XSS 취약점 수정 2026-01-27 05:50:34 +00:00
b94771de92 썸네일 파일 코드 위치변경 2026-01-27 03:34:20 +00:00
b29e16a198 게시판 관리자가 게시판 수정시 자동등록방지 숫자가 틀렸습니다 라고 나오는 오류 수정 2026-01-26 09:40:43 +00:00
0e06b4f9ce 영카트5에서 사용자가 현금영수증 발급버튼이 출력되지 않는 오류 수정 2026-01-26 09:33:19 +00:00
ab386ad965 잘못된 경로 주석처리(CDN 사용 안함 처리) 2025-12-26 15:48:02 +09:00
002ea55bcf 필요없는 파일 제거 2025-12-26 15:47:49 +09:00
f2ab751e5f [KVE-2025-0828]영카트 취약점 수정 2025-11-14 07:30:47 +00:00
3432497efe 삼성브라우저PC버전 대응 2025-11-14 02:08:02 +00:00
60bb03049e Merge pull request #61 from gnuboard/fix/admin-member-header
style: 관리자 > 회원관리 > 목록, 광고성 정보 수신 동의에 따른 테이블 폭 조정 처리
2025-09-25 10:07:49 +09:00
a7541256cb style: 관리자 > 회원관리 > 목록, 광고성 정보 수신 동의에 따른 테이블 폭 조정 처리 2025-09-25 10:02:25 +09:00
44 changed files with 677 additions and 9346 deletions

View File

@ -39,14 +39,17 @@ $bo_include_tail = isset($_POST['bo_include_tail']) ? preg_replace(array("#[\\\]
$check_captcha = false;
// 관리자가 자동등록방지 CAPTCHA를 사용해야 할 경우
if ($w === 'u') {
if (isset($board['bo_include_head'], $board['bo_include_tail']) &&
($board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail)) {
$check_captcha = true;
}
} elseif ($w === '') {
if ($bo_include_head !== '_head.php' || $bo_include_tail !== '_tail.php') {
$check_captcha = true;
// 최고 관리자인 경우에만 수정가능
if ($is_admin === 'super') {
if ($w === 'u') {
if (isset($board['bo_include_head'], $board['bo_include_tail']) &&
($board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail)) {
$check_captcha = true;
}
} elseif ($w === '') {
if ($bo_include_head !== '_head.php' || $bo_include_tail !== '_tail.php') {
$check_captcha = true;
}
}
}

View File

@ -587,7 +587,7 @@ td.td_grpset {width:160px;border-left:1px solid #e9ecee;text-align:center}
.td_time{text-align:center;width:130px}
.td_center{text-align:center;}
.td_type{width:120px}
.td_consent{width:200px}
.td_consent{min-width:70px;max-width:200px}
.td_mng_s{width:60px}
.td_mng_m{width:100px}

View File

@ -127,7 +127,7 @@ $colspan = 16;
<th scope="col" rowspan="2" id="mb_list_cert"><?php echo subject_sort_link('mb_certify', '', 'desc') ?>본인확인</a></th>
<th scope="col" id="mb_list_mailc"><?php echo subject_sort_link('mb_email_certify', '', 'desc') ?>메일인증</a></th>
<th scope="col" id="mb_list_open"><?php echo subject_sort_link('mb_open', '', 'desc') ?>정보공개</a></th>
<th scope="col" id="mb_list_mailr"><?php echo subject_sort_link('mb_mailling', '', 'desc') ?>광고성이메일수신</a></th>
<th scope="col" id="mb_list_mailr"><?php echo subject_sort_link('mb_mailling', '', 'desc') ?>광고성이메일</a></th>
<th scope="col" id="mb_list_auth">상태</th>
<th scope="col" id="mb_list_mobile">휴대폰</th>
<th scope="col" id="mb_list_lastcall"><?php echo subject_sort_link('mb_today_login', '', 'desc') ?>최종접속</a></th>
@ -137,9 +137,9 @@ $colspan = 16;
<tr>
<th scope="col" id="mb_list_name"><?php echo subject_sort_link('mb_name') ?>이름</a></th>
<th scope="col" id="mb_list_nick"><?php echo subject_sort_link('mb_nick') ?>닉네임</a></th>
<th scope="col" id="mb_list_sms"><?php echo subject_sort_link('mb_sms', '', 'desc') ?>광고성SMS/카카오톡수신</a></th>
<th scope="col" id="mb_list_adultc"><?php echo subject_sort_link('mb_adult', '', 'desc') ?>성인인증</a></th>
<th scope="col" id="mb_list_auth"><?php echo subject_sort_link('mb_intercept_date', '', 'desc') ?>접근차단</a></th>
<th scope="col" id="mb_list_sms"><?php echo subject_sort_link('mb_sms', '', 'desc') ?>광고성SMS</a></th>
<th scope="col" id="mb_list_deny"><?php echo subject_sort_link('mb_level', '', 'desc') ?>권한</a></th>
<th scope="col" id="mb_list_tel">전화번호</th>
<th scope="col" id="mb_list_join"><?php echo subject_sort_link('mb_datetime', '', 'desc') ?>가입일</a></th>
@ -258,7 +258,7 @@ $colspan = 16;
<input type="checkbox" name="mb_open[<?php echo $i; ?>]" <?php echo $row['mb_open'] ? 'checked' : ''; ?> value="1" id="mb_open_<?php echo $i; ?>">
</td>
<td headers="mb_list_mailr" class="td_consent">
<label for="mb_mailling_<?php echo $i; ?>" class="sound_only">메일수신</label>
<label for="mb_mailling_<?php echo $i; ?>" class="sound_only">광고성이메일수신</label>
<input type="checkbox" name="mb_mailling[<?php echo $i; ?>]" <?php echo $row['mb_mailling'] ? 'checked' : ''; ?> value="1" id="mb_mailling_<?php echo $i; ?>">
<input type="hidden" name="mb_mailling_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_mailling']) ? $row['mb_mailling'] : '0'; ?> " id="mb_mailling_default_<?php echo $i; ?>">
</td>
@ -281,12 +281,6 @@ $colspan = 16;
<td headers="mb_list_nick" class="td_name sv_use">
<div><?php echo $mb_nick ?></div>
</td>
<td headers="mb_list_sms">
<label for="mb_sms_<?php echo $i; ?>" class="sound_only">SMS수신</label>
<input type="checkbox" name="mb_sms[<?php echo $i; ?>]" <?php echo $row['mb_sms'] ? 'checked' : ''; ?> value="1" id="mb_sms_<?php echo $i; ?>">
<input type="hidden" name="mb_sms_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_sms']) ? $row['mb_sms'] : '0'; ?> " id="mb_sms_default_<?php echo $i; ?>">
</td>
<td headers="mb_list_adultc">
<label for="mb_adult_<?php echo $i; ?>" class="sound_only">성인인증</label>
<input type="checkbox" name="mb_adult[<?php echo $i; ?>]" <?php echo $row['mb_adult'] ? 'checked' : ''; ?> value="1" id="mb_adult_<?php echo $i; ?>">
@ -297,6 +291,11 @@ $colspan = 16;
<label for="mb_intercept_date_<?php echo $i; ?>" class="sound_only">접근차단</label>
<?php } ?>
</td>
<td headers="mb_list_sms">
<label for="mb_sms_<?php echo $i; ?>" class="sound_only">광고성SMS/카카오톡수신</label>
<input type="checkbox" name="mb_sms[<?php echo $i; ?>]" <?php echo $row['mb_sms'] ? 'checked' : ''; ?> value="1" id="mb_sms_<?php echo $i; ?>">
<input type="hidden" name="mb_sms_default[<?php echo $i; ?>]" value="<?php echo isset($row['mb_sms']) ? $row['mb_sms'] : '0'; ?> " id="mb_sms_default_<?php echo $i; ?>">
</td>
<td headers="mb_list_auth" class="td_mbstat">
<?php echo get_member_level_select("mb_level[$i]", 1, $member['mb_level'], $row['mb_level']) ?>
</td>

View File

@ -64,6 +64,8 @@ foreach($check_skin_keys as $key){
if( isset($_POST[$key]) && preg_match('#\.+(\/|\\\)#', $_POST[$key]) ){
alert('스킨설정에 유효하지 문자가 포함되어 있습니다.');
}
$$key = $_POST[$key] = sql_real_escape_string($_POST[$key]);
}
// 현금영수증 발급수단

View File

@ -67,7 +67,9 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
for ($i=0; $i<$len; $i++)
$nbsp .= "&nbsp;&nbsp;&nbsp;";
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
}
// 모바일 1줄당 이미지수 필드 추가

View File

@ -107,7 +107,9 @@ if($ev_id) {
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -146,9 +146,11 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
$nbsp = "";
for ($i=0; $i<$len; $i++)
$nbsp .= "&nbsp;&nbsp;&nbsp;";
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
// 전체 카테고리 경로 표시 (예: 남성의류 > 상의 > 셔츠)
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
$category_select .= "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
$script .= "ca_use['{$row['ca_id']}'] = {$row['ca_use']};\n";
$script .= "ca_stock_qty['{$row['ca_id']}'] = {$row['ca_stock_qty']};\n";
//$script .= "ca_explan_html['$row[ca_id]'] = $row[ca_explan_html];\n";
@ -1394,7 +1396,9 @@ $(function(){
for ($i=0; $i<$len; $i++)
$nbsp .= "&nbsp;&nbsp;&nbsp;";
echo "<option value=\"{$row['ca_id']}\">$nbsp{$row['ca_name']}</option>\n";
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
echo "<option value=\"{$row['ca_id']}\">$nbsp{$category_path}</option>\n";
}
?>
</select>

View File

@ -25,7 +25,8 @@ for ($i=0; $row=sql_fetch_array($result); $i++)
for ($i=0; $i<$len; $i++) {
$nbsp .= '&nbsp;&nbsp;&nbsp;';
}
$ca_list .= '<option value="'.$row['ca_id'].'">'.$nbsp.$row['ca_name'].'</option>'.PHP_EOL;
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row['ca_id']) : $row['ca_name'];
$ca_list .= '<option value="'.$row['ca_id'].'">'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
$where = " and ";
@ -100,7 +101,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = '';
for ($i=0; $i<$len; $i++) $nbsp .= '&nbsp;&nbsp;&nbsp;';
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -79,7 +79,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
$selected = ($row1['ca_id'] == $sca) ? ' selected="selected"' : '';
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -83,7 +83,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -82,7 +82,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -98,7 +98,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sca, $row1['ca_id']).'>'.$nbsp.$category_path.PHP_EOL;
}
?>
</select>

View File

@ -81,7 +81,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
$selected = ($row1['ca_id'] == $sca) ? ' selected="selected"' : '';
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'"'.$selected.'>'.$nbsp.$category_path.PHP_EOL;
}
?>
</select>

View File

@ -84,7 +84,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$row1['ca_name'].'</option>'.PHP_EOL;
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo '<option value="'.$row1['ca_id'].'" '.get_selected($sel_ca_id, $row1['ca_id']).'>'.$nbsp.$category_path.'</option>'.PHP_EOL;
}
?>
</select>

View File

@ -71,7 +71,9 @@ $listall = '<a href="'.$_SERVER['SCRIPT_NAME'].'" class="ov_listall">전체목
$len = strlen($row1['ca_id']) / 2 - 1;
$nbsp = "";
for ($i=0; $i<$len; $i++) $nbsp .= "&nbsp;&nbsp;&nbsp;";
echo "<option value='{$row1['ca_id']}'".get_selected($row1['ca_id'], $sel_ca_id).">$nbsp{$row1['ca_name']}\n";
// 전체 카테고리 경로 표시
$category_path = function_exists('get_shop_category_path') ? get_shop_category_path($row1['ca_id']) : $row1['ca_name'];
echo "<option value='{$row1['ca_id']}'".get_selected($row1['ca_id'], $sel_ca_id).">$nbsp{$category_path}\n";
}
?>
</select>

View File

@ -40,6 +40,12 @@ if ($type) {
else
$mail_content = $content;
// 환경설정에서 폼메일 사용 여부가 회원만 사용에 체크되어 있으면
if ($config['cf_formmail_is_member']) {
$fnick = (isset($member['mb_nick']) && $member['mb_nick']) ? $member['mb_nick'] : $member['mb_name'];
$fmail = $member['mb_email'];
}
mailer($fnick, $fmail, $to, $subject, $mail_content, $type, $file);
// 임시 첨부파일 삭제

View File

@ -346,8 +346,10 @@ if ($w == '') {
}
for($i=0;$i<$file_count;$i++){
if(! isset($file[$i])) {
if (!isset($file[$i])) {
$file[$i] = array('file'=>null, 'source'=>null, 'size'=>null, 'bf_content' => null);
} else {
$file[$i]['bf_content'] = isset($file[$i]['bf_content']) ? htmlspecialchars($file[$i]['bf_content'], ENT_QUOTES, 'UTF-8', false) : null;
}
}

View File

@ -173,7 +173,7 @@ define('G5_DIR_PERMISSION', 0755); // 디렉토리 생성시 퍼미션
define('G5_FILE_PERMISSION', 0644); // 파일 생성시 퍼미션
// 모바일 인지 결정 $_SERVER['HTTP_USER_AGENT']
define('G5_MOBILE_AGENT', 'phone|samsung|lgtel|mobile|[^A]skt|nokia|blackberry|BB10|android|sony');
define('G5_MOBILE_AGENT', 'phone|samsung.*mobile|lgtel|mobile|[^A]skt|nokia|blackberry|BB10|android|sony');
// SMTP
// lib/mailer.lib.php 에서 사용

View File

@ -16,7 +16,7 @@ define('FG_MANAGER_PATH', G5_PATH.'/'.FG_MANAGER_DIR);
// define('FG_MANAGER_PATH', G5_ADMIN_PATH.'/'.FG_MANAGER_DIR);
// 퍼스트가든 caf24 CDN 경로
include_once G5_PATH.'/fg_config.php';
// include_once G5_PATH.'/fg_config.php';
// define('CDN_URL', G5_URL.'/image');
// define('CDN_URL', 'https://firstgarden.cdn3.cafe24.com');

File diff suppressed because one or more lines are too long

View File

@ -158,7 +158,7 @@ if ($g5_install || $is_install === false) {
cf_theme = 'basic',
cf_admin = '$admin_id',
cf_admin_email = '$admin_email',
cf_admin_email_name = '".G5_VERSION."',
cf_admin_email_name = '".G5_VERSION.'_'.substr(base_convert(mt_rand(), 10, 36), 0, 6)."',
cf_use_point = '1',
cf_use_copy_log = '1',
cf_login_point = '100',

View File

@ -3951,10 +3951,16 @@ class str_encrypt
function __construct($salt='')
{
if(!$salt)
$this->salt = md5(preg_replace('/[^0-9A-Za-z]/', substr(G5_MYSQL_USER, -1), $_SERVER['SERVER_SOFTWARE'].$_SERVER['DOCUMENT_ROOT']));
else
global $config;
if (!$salt) {
$config_hash = md5(serialize(array($config['cf_title'], $config['cf_theme'], $config['cf_admin_email_name'], $config['cf_login_point'], $config['cf_memo_send_point'])));
//$this->salt = md5(preg_replace('/[^0-9A-Za-z]/', substr($config_hash, -1), $_SERVER['SERVER_SOFTWARE'].$config_hash.$_SERVER['DOCUMENT_ROOT']));
$this->salt = hash('sha256', preg_replace('/[^0-9A-Za-z]/', substr($config_hash, -1), $_SERVER['SERVER_SOFTWARE'].$config_hash.$_SERVER['DOCUMENT_ROOT']));
} else {
$this->salt = $salt;
}
$this->length = strlen($this->salt);
}

View File

@ -2461,7 +2461,7 @@ function get_itemuselist_thumbnail($it_id, $contents, $thumb_width, $thumb_heigh
}
function shop_is_taxsave($od, $is_view_receipt=false){
global $default, $is_memeber;
global $default, $is_member;
$od_pay_type = '';
@ -2770,6 +2770,50 @@ function get_item_images_info($it, $size=array(), $image_width=0, $image_height=
return $images;
}
// 카테고리 전체 경로를 가져오는 함수 (예: 남성의류 > 상의 > 셔츠)
function get_shop_category_path($ca_id, $separator = ' &gt; ')
{
global $g5;
static $category_cache = array(); // 카테고리명 캐시
static $path_cache = array(); // 경로 캐시
if (!$ca_id) return '';
// 동일한 separator로 이미 조회한 경로가 있으면 캐시에서 반환
$cache_key = $ca_id . '|' . $separator;
if (isset($path_cache[$cache_key])) {
return $path_cache[$cache_key];
}
$path_arr = array();
$ca_id_len = strlen($ca_id);
// 카테고리 ID를 2자리씩 분할하여 각 단계의 카테고리명을 조회
for ($i = 2; $i <= $ca_id_len; $i += 2) {
$current_ca_id = substr($ca_id, 0, $i);
// 캐시에 없으면 DB 조회
if (!isset($category_cache[$current_ca_id])) {
$sql = " select ca_name from {$g5['g5_shop_category_table']} where ca_id = '$current_ca_id' ";
$row = sql_fetch($sql);
if ($row) {
$category_cache[$current_ca_id] = $row['ca_name'];
} else {
$category_cache[$current_ca_id] = '';
}
}
if ($category_cache[$current_ca_id]) {
$path_arr[] = $category_cache[$current_ca_id];
}
}
$result = implode($separator, $path_arr);
$path_cache[$cache_key] = $result; // 결과를 캐시에 저장
return $result;
}
function check_payment_method($od_settle_case) {
global $default;

View File

@ -275,11 +275,10 @@ function thumbnail($filename, $source_path, $target_path, $thumb_width, $thumb_h
$thumb_filename = preg_replace("/\.[^\.]+$/i", "", $filename); // 확장자제거
// $thumb_file = "$target_path/thumb-{$thumb_filename}_{$thumb_width}x{$thumb_height}.".$ext[$size[2]];
$thumb_file = "$target_path/thumb-{$thumb_filename}_{$thumb_width}x{$thumb_height}.".$file_ext;
$thumb_time = @filemtime($thumb_file);
$source_time = @filemtime($source_file);
if (file_exists($thumb_file)) {
$thumb_time = @filemtime($thumb_file);
$source_time = @filemtime($source_file);
if ($is_create == false && $source_time < $thumb_time) {
return basename($thumb_file);
}

View File

@ -5,17 +5,17 @@ if (!isset($_SESSION['user_id'])) header( 'Location: FG_MANAGER_URL' ); // 로
include_once FG_MANAGER_PATH."/head.php";
$table = "{$fg['member_table']} AS a LEFT JOIN {$fg['member_group_table']} AS b ON a.tid = b.tid";
if ( $_SESSION['user_lv'] == 4 ) { // 시스템관리자는 모든 계정 열람 가능함
$where = "";
} else { // 아닌경우 로그인 계정과 동일 부서이면서 낮은 등급의 계정만 처리가능
if ( $_SESSION['user_lv'] != 4 ) { // 시스템관리자는 모든 계정 열람 가능함
$where = "WHERE user_lv < '{$_SESSION['user_lv']}' AND tname = '{$_SESSION['user_team']}' OR user_id = '{$_SESSION['user_id']}'";
}
$record_count = get_num_rows($table);
$ord_by = " ORDER BY idx ASC ";
$ord_by = " ORDER BY a.used DESC, b.tname ASC, a.idx ASC ";
$R = get_result($table, $ord_by, $query_limit, $where);
?>
<div class="d-flex justify-content-between align-items-center">
<p>전체 계정 수 : <b><?=$record_count; ?></b></p>
<div class="d-flex align-items-center gap-2">
<p class="mb-0">전체 계정 수 : <b><?=$record_count; ?></b></p>
</div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#add_modal">추가</button>
</div>
<div class="text-center">
@ -46,9 +46,10 @@ include_once FG_MANAGER_PATH."/head.php";
</thead>
<!-- 목록 출력 -->
<tbody>
<?php foreach($R as $R){ ?>
<tr class="<?=($R['used'] == 1) ? "" : "unused"?>">
<!--<td class="text-center"><?=$R['idx']?></td>-->
<?php foreach($R as $R){
?>
<tr class="<?=($R['used'] == 1) ? "" : "unused"?> " >
<!-- <td class="text-center"><?=$R['idx']?></td> -->
<td class="text-center align-middle"><?=$R['tname']?></td>
<td class="text-center"><?=$R['user_name']?></td>
<td class="text-center"><?=$R['user_id']?></td>

View File

@ -0,0 +1,64 @@
<?php
//if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
include_once('_common.php');
include_once('../config.php');
$sql_common = "SELECT * FROM {$fg['annual_member_table']} AS a LEFT JOIN {$fg['annual_category_table']} AS b ON a.ca_id = b.ca_id";
$result = sql_query($sql_common);
$file_name = "annual_member_list_".date("ymd")."_".date("His").".xls"; // 파일명지정
header("Content-Type: application/vnd.ms-excel");
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
header("Content-Disposition: attachment; filename=$file_name");
header("Content-Description: PHP Generated Data");
?>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style type="text/css">
.tit {background-color:#C0C0C0; height:30px; }
.no-text {mso-number-format:'\@'; text-align:center;}
</style>
<table cellspacing="0" cellpadding="0" border="1">
<thead>
<tr>
<th class="tit">회원번호</th>
<th class="tit">권종구분</th>
<th class="tit">상태</th>
<th class="tit">성명</th>
<th class="tit">연락처</th>
<th class="tit">생년월일</th>
<th class="tit">메모</th>
<th class="tit">시작일</th>
<th class="tit">종료일</th>
<th class="tit">이메일</th>
<th class="tit">주소</th>
<th class="tit">최종이용일</th>
<th class="tit">이용횟수</th>
</tr>
</thead>
<tbody>
<?php
for ($i=0; $row=sql_fetch_array($result); $i++) { // 반복문 시작
?>
<tr>
<td class="no-text"><?php echo $row['mem_no']; ?> </td>
<td class="no-text"><?php echo $row['ca_name']?> </td>
<td class="no-text"><?php echo $row['status']?> </td>
<td style="text-align:center"> <?php echo $row['name']?> </td>
<td class="no-text"><?php echo $row['tel']; ?></td>
<td style="text-align:center"> <?php echo $row['birth']?> </td>
<td style="text-align:center"> <?php echo $row['memo'];?> </td>
<td style="text-align:center"> <?php echo $row['sdate'];?> </td>
<td style="text-align:center"> <?php echo $row['edate']?> </td>
<td class="no-text"><?php echo $row['email']; ?> </td>
<td class="no-text"><?php echo $row['addr']; ?> </td>
<td class="no-text"><?php echo ($row['last_ent_date'] == '0000-00-00 00:00:00') ? '미이용' : date('Y-m-d', strtotime($row['last_ent_date'])); ?> </td>
<td class="no-text"><?php echo $row['ent_count']; ?> </td>
</tr>
<?php } // 반복문 종료 ?>
</tbody>
</table>

View File

@ -80,7 +80,7 @@ $set_annual_status = array("정상", "검토대기", "만료");
<p>전체 회원 수 : <b><?=$record_count?></b> | 검색 회원 수 : <?=$search_count ? $search_count : $record_count?></p>
</div>
<div class="d-flex flex-row-reverse column-gap-2">
<form method="post" action="inc/annual_member_list_excel.php">
<form method="post" action="annual_member_list.excel.php">
<button type="submit" class="btn btn-secondary" >엑셀저장</button>
</form>
<?php if($_SESSION['user_lv'] > "1"){ // 추가 권한 체크 ?>

View File

@ -49,7 +49,7 @@ if( isset($search_word) && $search_word ) { // 검색어가 있을때만 돌림
<th class="text-center">회원번호</th>
<th class="text-center">상태</th>
<th class="text-center">회원구분</th>
<th class="text-center">대표성명</th>
<!--<th class="text-center">대표성명</th>-->
<th class="text-center">성명</th>
<th class="text-center">연락처</th>
<th class="text-center">입장횟수</th>
@ -64,7 +64,7 @@ if( isset($search_word) && $search_word ) { // 검색어가 있을때만 돌림
<td class="text-center"><?=sprintf("%06d",$R['mem_no'])?></td>
<td class="text-center"><?=$R['status']?></td>
<td class="text-center"><?=$R['ca_name']?></td>
<td class="text-center"><?=$R['rep_name']?></td>
<!--<td class="text-center"><?=$R['rep_name']?></td>-->
<td class="text-center"><?=$R['name']?></td>
<td class="text-center"><?=$R['tel']?></td>
<td class="text-center"><?=$R['ent_count']?></td>

View File

@ -43,9 +43,9 @@ $query_limit = "LIMIT ".(($p - 1) * $recnum).",".$recnum; // 출력할 아이템
// 권한설정
$pageAuth = [
'bakery' => ['bakery', 'firstgarden'],
'vip' => ['ticket', 'firstgarden', 'service', 'gift', 'heyum', 'dksdpwl'],
'vip' => ['ticket', 'firstgarden', 'service', 'gift', 'heyum', 'dksdpwl', '39365260', 'reservation'],
'ticket' => ['ticket'],
'admin' => ['abc']
'admin' => ['abc', '39365260']
];
// page 설정

View File

@ -35,11 +35,17 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
<label class="btn btn-outline-primary" for="search_group_all">전체</label>
<?php
$group_name = getVipCatName();
$show_all = isset($_REQUEST['show_all_cat']) ? true : false;
foreach ($group_name as $row) { // VIP구분 가지고 와서 뿌려주기
$inactive_class = ($row['gr_used'] == 0) ? ' inactive-cat' : '';
$display_style = ($row['gr_used'] == 0) ? 'display: none;' : '';
?>
<input type="radio" name="search_group" id="search_group_<?=$row['gr_id']?>" class="btn-check" value="<?=$row['gr_id']?>" <?php if ($search_group === $row['gr_id']) echo "checked" ?>>
<label class="btn btn-outline-primary" for="search_group_<?=$row['gr_id']?>"><?=$row['gr_name']?></label>
<?php } ?>
<input type="radio" name="search_group" id="search_group_<?=$row['gr_id']?>" class="btn-check<?=$inactive_class?>" value="<?=$row['gr_id']?>" <?php if ($search_group === $row['gr_id']) echo "checked" ?> style="<?=$display_style?>">
<label class="btn btn-outline-primary category-label<?=$inactive_class?>" for="search_group_<?=$row['gr_id']?>" style="<?=($row['gr_used'] == 0) ? 'opacity: 0.5;' : ''?><?=$display_style?>"><?=$row['gr_name']?></label>
<?php } // endforeach ?>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="toggleShowAllCat()" data-show-all="<?=($show_all) ? 'true' : 'false'?>">
<?=($show_all) ? '활성만 보기' : '모두보기'?>
</button>
</div>
<div class="input-group col-md-6">
<span class="input-group-text" id="search_word">회원검색</span>
@ -157,6 +163,7 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
<col width="130px">
<col width="100px">
<col width="90px">
<col width="90px">
<col width="50px">
<col width="100px">
</colgroup>
@ -167,6 +174,7 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
<th class="text-center">성명</th>
<th class="text-center">연락처</th>
<th class="text-center">생년월일</th>
<th class="text-center">만료일</th>
<th class="text-center">최종이용일</th>
<th class="text-center">방문횟수</th>
<?php if($_SESSION['user_lv'] > "1"){ ?>
@ -175,37 +183,46 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
</tr>
</thead>
<tbody class="table-group-divider">
<?php foreach($R as $R) {?>
<tr class="<?=($R['status'] != '정상') ? "unused" : "" ?>">
<td class="text-center"><?=$R['vip_card_no']?></td>
<td class="text-center"><?=$R['status']?></td>
<td class="text-center"><?=$R['vip_name']?></td>
<td class="text-center"><?=$R['vip_tel']?></td>
<td class="text-center"><?=$R['vip_birth']?></td>
<td class="text-center">
<?php foreach($R as $R) {
$today = date('Y-m-d');
$expire_date = $R['vip_date'];
$is_expired = ($expire_date != '9999-12-31' && strtotime($expire_date) < strtotime($today)) ? true : false;
$expired_class = $is_expired ? 'expired-vip' : '';
?>
<tr class="<?=($R['status'] != '정상') ? "unused" : "" ?> vip-row <?=$expired_class?>" style="cursor: pointer; height: 60px;" onclick="handleRowClick(event, '<?=$R['idx']?>')">
<td class="text-center align-middle"><?=$R['vip_card_no']?></td>
<td class="text-center align-middle"><?=$R['status']?></td>
<td class="text-center align-middle"><?=$R['vip_name']?></td>
<td class="text-center align-middle"><?=$R['vip_tel']?></td>
<td class="text-center align-middle"><?=$R['vip_birth']?></td>
<td class="text-center align-middle"><?=($R['vip_date'] == '9999-12-31')? '평생' : $R['vip_date']?></td>
<td class="text-center align-middle">
<?php
$edate = $R['last_ent_date'];
echo ($edate == '0000-00-00 00:00:00')? '미이용' : date('Y-m-d',strtotime($edate));
?></td>
<td class="text-center"><?=$R['ent_count']?></td>
<td class="text-center d-flex justify-content-center gap-1">
<td class="text-center align-middle"><?=$R['ent_count']?></td>
<td class="text-center align-middle d-flex justify-content-center gap-1 action-cell" onclick="event.stopPropagation();" style="min-height: 60px;">
<?php if($_SESSION['user_lv'] > "1"){ ?>
<!-- 입장처리 버튼 -->
<?php if ($R['status'] == '정상') { ?>
<a class="btn btn-danger btn-xs" href="javascript:entMem('<?=$R['idx']?>')" role="button"><i class="fas fa-sign-in-alt"></i></a>
<?php } else { ?>
<i class="fas fa-times"></i>
<?php if($R['status'] == '정상' || $R['status'] == '만료') { ?>
<a class="btn btn-danger btn-xs" href="#" onclick="event.preventDefault(); event.stopPropagation(); entMemWithConfirm('<?=$R['idx']?>', <?=$is_expired ? 'true' : 'false'?>);" role="button"><i class="fas fa-sign-in-alt"></i></a>
<button type="button" class="btn btn-success btn-xs" data-bs-toggle="modal" data-bs-target="#modify_modal_<?=$R['idx']?>" onclick="event.stopPropagation()"><i class="fa-solid fa-pen-to-square"></i></button>
<button type="button" class="btn btn-primary btn-xs" data-bs-toggle="modal" data-bs-target="#renew_modal_<?=$R['idx']?>" onclick="event.stopPropagation()"><i class="fa-solid fa-repeat"></i></button>
<?php } ?>
<!-- 입장처리 버튼 끝 -->
<!-- 수정 모달 -->
<?php if($_SESSION['user_lv'] === "4" && $R['status'] != "재발급"){ ?>
<a class="btn btn-danger btn-xs" href="#" onclick="event.preventDefault(); event.stopPropagation(); deleteItem('<?=$R['idx']?>');" role="button"><?=($R['status'] == '정상')? '<i class="fa-solid fa-trash-can"></i>' : '<i class="fa-solid fa-trash-can-arrow-up"></i>'?></a>
<?php } ?>
<?php } ?>
</td>
</tr>
<div id="modify_modal_<?=$R['idx']?>" class="modal fade" tabindex="-1" aria-labelledby="modify_modal_<?=$R['idx']?>" aria-hidden="true">
<div class="modal-dialog modal modal-dialog-centered">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form class="modify" id="modify_<?=$R['idx']?>">
<div class="modal-header">
<h5 class="modal-title">정보 보기/수정</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-start">
<input type="hidden" id="idx_<?=$R['idx']?>" name="idx" value="<?=$R['idx']?>" readonly>
@ -216,7 +233,10 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
if($R['status'] != "정상") {
$ro = "disabled";
echo "<p>폐기된 카드는 수정할 수 없습니다.</p>";
;
}
$gender = '';
if($R['status'] == "정상") {
$gender = $R['vip_gender'];
}
?>
<div class="input-group mb-1">
@ -254,11 +274,7 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
<div class="input-group mb-1">
<span class="input-group-text col-md-2" id="vip_name_<?=$R['idx']?>">고객명</span>
<input type="text" class="form-control" id="vip_name_<?=$R['idx']?>" name="vip_name" value="<?=$R['vip_name']?>" required <?=$ro?>>
<? // DB에서 성별값을 불러온다.
if($R['status'] == "정상") { // 정상 상태가 아니면 성별도 필요없음
$gender = $R['vip_gender']
?>
<!-- 불러온 성별에 따라 라디오버튼 선택하도록 -->
<?php if($R['status'] == "정상") { ?>
<input type="radio" class="btn-check" name="vip_gender" id="vip_gender_<?=$R['idx']?>_male" value="남" <?php if($gender == "남") echo "checked" ?> required>
<label class="btn btn-outline-primary" for="vip_gender_<?=$R['idx']?>_male">남</label>
<input type="radio" class="btn-check" name="vip_gender" id="vip_gender_<?=$R['idx']?>_female" value="여" <?php if($gender =="여") echo "checked" ?> required>
@ -286,56 +302,113 @@ $table = "{$fg['vip_list_table']} AS a LEFT JOIN {$fg['vip_category_table']} AS
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" <?=$ro?> >수정</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" aria-label="Close" data-bs-target="#modify_modal_<?=$R['idx']?>">닫기</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</div>
</div>
<!-- 수정 모달 끝 -->
<!-- 수정 버튼 -->
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#modify_modal_<?=$R['idx']?>"><i class="fa-solid fa-pen-to-square"></i></button>
<!-- 재발급 버튼 -->
<?php if ( $R['status'] === "정상" ) { ?>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#renew_modal_<?=$R['idx']?>"><i class="fa-solid fa-repeat"></i></button>
<div id="renew_modal_<?=$R['idx']?>" class="modal fade text-center ">
<div class="modal-dialog">
<div class="modal-content">
<form class="renew" id="renew_<?=$R['idx']?>">
<input type="hidden" id="idx_<?=$R['idx']?>" name="idx" value="<?=$R['idx']?>" readonly>
<input type="hidden" id="last_edit_name_<?=$R['idx']?>" name="last_edit_name" value="<?=$_SESSION['user_name']?>" readonly>
<div class="modal-header">
<h5 class="modal-title">재발급</h4>
<!-- 재발급 모달 -->
<?php if ( $R['status'] === "정상" ) { ?>
<div id="renew_modal_<?=$R['idx']?>" class="modal fade" tabindex="-1" aria-labelledby="renew_modal_<?=$R['idx']?>" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form class="renew" id="renew_<?=$R['idx']?>">
<input type="hidden" id="idx_<?=$R['idx']?>" name="idx" value="<?=$R['idx']?>" readonly>
<input type="hidden" id="last_edit_name_<?=$R['idx']?>" name="last_edit_name" value="<?=$_SESSION['user_name']?>" readonly>
<div class="modal-header">
<h5 class="modal-title">재발급</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-start">
<div class="input-group">
<span class="input-group-text col-md-4" id="re_no_<?=$R['idx']?>">재발급 카드번호</span>
<input type="number" class="form-control" oninput="checkDupRc(this.value)" id="rc_no_<?=$R['idx']?>" name="rc_no" maxlength="6" value="" required>
</div>
<div class="modal-body text-start">
<div class="input-group">
<span class="input-group-text col-md-4" id="re_no_<?=$R['idx']?>">재발급 카드번호</span>
<input type="number" class="form-control" oninput="checkDupRc(this.value)" id="rc_no_<?=$R['idx']?>" name="rc_no" maxlength="6" value="" required>
</div>
<div class="input-group checkdup">
<span id="duplicate-rc-warning"></span>
</div>
<div class="input-group checkdup">
<span id="duplicate-rc-warning"></span>
</div>
<div class="modal-footer">
<button type="submit" id="renew_submit" class="btn btn-primary">확인</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" aria-label="Close" data-bs-target="#renew_modal_<?=$R['idx']?>">닫기</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal-footer">
<button type="submit" id="renew_submit" class="btn btn-primary">확인</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
</div>
</form>
</div>
</div>
<?php } ?>
<!-- 폐기는 관리자만 -->
<?php if($_SESSION['user_lv'] === "4" && $R['status'] != "재발급"){ ?>
<a class="btn btn-danger" href="javascript:deleteItem('<?=$R['idx']?>')" role="button"><?=($R['status'] == '정상')? '<i class="fa-solid fa-trash-can"></i>' : '<i class="fa-solid fa-trash-can-arrow-up"></i>'?></a>
<?php }
} ?>
</td>
</tr>
</div>
<?php } ?>
<?php } ?>
</tbody>
</table>
</div>
<style>
.expired-vip {
color: #777;
}
.expired-vip td {
color: #999 !important;
}
.vip-row:hover {
background-color: #f5f5f5;
}
.inactive-cat {
opacity: 0.6;
}
</style>
<script>
function handleRowClick(event, idx) {
// 작업 셀을 클릭했는지 확인
if (event.target.closest('.action-cell')) {
return;
}
const modal = new bootstrap.Modal(document.getElementById('modify_modal_' + idx));
modal.show();
}
function toggleShowAllCat() {
const btn = event.target;
const showAll = !btn.getAttribute('data-show-all') || btn.getAttribute('data-show-all') === 'false';
// 비활성 카테고리 input과 label 토글
const inactiveElements = document.querySelectorAll('.inactive-cat');
inactiveElements.forEach(elem => {
elem.style.display = showAll ? 'inline-block' : 'none';
});
// 버튼 텍스트 업데이트
btn.textContent = showAll ? '활성만 보기' : '모두보기';
btn.setAttribute('data-show-all', showAll ? 'true' : 'false');
// URL 업데이트 (새로고침 없음)
const url = new URL(window.location);
if (showAll) {
url.searchParams.set('show_all_cat', '1');
} else {
url.searchParams.delete('show_all_cat');
}
window.history.pushState({}, '', url.toString());
}
function openVipModal(idx) {
const modal = document.getElementById('modify_modal_' + idx);
if (modal) {
const bsModal = new bootstrap.Modal(modal);
bsModal.show();
}
}
function entMemWithConfirm(idx, isExpired) {
let confirmMsg = isExpired ? '만료된 회원입니다. 입장처리 하시겠습니까?' : '입장처리 하시겠습니까?';
if (confirm(confirmMsg)) {
entMem(idx);
}
}
</script>
<?php include_once FG_MANAGER_PATH."/tail.php";

View File

@ -14,9 +14,15 @@ if(isset($_POST['mode']) && trim($_POST['mode']) === "enter") {
$date = date("Y-m-d");
$datetime = date("Y-m-d H:i:s");
// 만료일 설정 로직
// 현재 최종이용일 + 1년
$vip_date = date("Y-m-d", strtotime($date . " +1 year"));
// 리스트 DB에 최종사용일자 업데이트
$listquery = "UPDATE {$fg['vip_list_table']} SET last_ent_date='{$date}', ent_count='{$ent_count}' WHERE idx='{$idx}'";
// 리스트 DB에 최종사용일자 및 만료일 업데이트
// 만료 상태였다면 정상으로 변경
$status_update = ($list['status'] === '만료') ? ", status='정상'" : '';
$listquery = "UPDATE {$fg['vip_list_table']} SET last_ent_date='{$date}', ent_count='{$ent_count}', vip_date='{$vip_date}'{$status_update} WHERE idx='{$idx}'";
$result = sql_query($listquery);
$data = array("isSuccess" => $result);
@ -30,7 +36,8 @@ if(isset($_POST['mode']) && trim($_POST['mode']) === "enter") {
// log 기록
$work = "VIP입장";
$work_detail = "카드번호 : ".$list['vip_card_no']." 처리자 : ".$_SESSION['user_name'];
$status_changed = ($list['status'] === '만료') ? " (상태변경: 만료→정상)" : "";
$work_detail = "카드번호 : ".$list['vip_card_no']." 만료일 설정 : ".$vip_date." 처리자 : ".$_SESSION['user_name'].$status_changed;
$logUpdate = log_update($work, $work_detail, $_SESSION['user_id'], $datetime);
if ($isDebug && !$logUpdate) echo '로그 등록 실패\n';

View File

@ -49,22 +49,27 @@ if( isset($search_word) && $search_word ) { // 검색어가 있을때만 돌림
<tr class="align-middle">
<th class="text-center">카드번호</th>
<th class="text-center">상태</th>
<th class="text-center">회원구분</th>
<!--<th class="text-center">회원구분</th>-->
<th class="text-center">성명</th>
<th class="text-center">연락처</th>
<th class="text-center">가입일</th>
<th class="text-center">입장횟수</th>
<th class="text-center">최종입장일</th>
<th class="text-center">VIP만료일</th>
<th class="text-center">만료일</th>
<th class="text-center">입장확인</th>
</tr>
</thead>
<tbody class="table-group-divider">
<?php foreach($R as $R) { ?>
<tr class="<?=($R['status'] != '정상') ? "unused" : "" ?>">
<?php foreach($R as $R) {
$today = date('Y-m-d');
$expire_date = $R['vip_date'];
$is_expired = ($expire_date != '9999-12-31' && strtotime($expire_date) < strtotime($today)) ? true : false;
$expired_class = $is_expired ? 'expired-vip' : '';
?>
<tr class="<?=($R['status'] != '정상') ? "unused" : "" ?> <?=$expired_class?>">
<td class="text-center"><?=sprintf("%06d",$R['vip_card_no'])?></td>
<td class="text-center"><?=$R['status']?></td>
<td class="text-center"><?=$R['gr_name']?></td>
<!--<td class="text-center"><?=$R['gr_name']?></td>-->
<td class="text-center"><?=$R['vip_name']?></td>
<td class="text-center"><?=$R['vip_tel']?></td>
<td class="text-center"><?=date('Y-m-d',strtotime($R['join_datetime']));?></td>
@ -76,8 +81,8 @@ if( isset($search_word) && $search_word ) { // 검색어가 있을때만 돌림
<?=($R['vip_date'] == "9999-12-31") ? "평생" : $R['vip_date']; ?>
</td>
<td class="text-center">
<?php if ($R['status'] == '정상') { ?>
<a class="btn btn-danger btn-xs" href="javascript:entMem('<?=$R['idx']?>')" role="button"><i class="fas fa-sign-in-alt"></i></a>
<?php if ($R['status'] == '정상' || $R['status'] == '만료' ) { ?>
<a class="btn btn-danger btn-xs" href="#" onclick="event.preventDefault(); entMemWithConfirm('<?=$R['idx']?>', <?=$is_expired ? 'true' : 'false'?>);" role="button"><i class="fas fa-sign-in-alt"></i></a>
<?php } else { ?>
<i class="fas fa-times"></i>
<?php } ?>
@ -93,4 +98,24 @@ if( isset($search_word) && $search_word ) { // 검색어가 있을때만 돌림
echo '<h2 style="margin-top: 30px; text-align: center;">검색 결과가 없습니다.</h2>'.PHP_EOL;
}
}
include_once FG_MANAGER_PATH."/tail.php";
?>
<style>
.expired-vip {
color: #777;
}
.expired-vip td {
color: #999 !important;
}
</style>
<script>
function entMemWithConfirm(idx, isExpired) {
let confirmMsg = isExpired ? '만료된 카드입니다. 입장처리 하시겠습니까?' : '입장처리 하시겠습니까?';
if (confirm(confirmMsg)) {
entMem(idx);
}
}
</script>
<?php include_once FG_MANAGER_PATH."/tail.php";

View File

@ -0,0 +1,257 @@
<?php
/**
* VIP 만료일 설정 페이지
* 방문횟수가 0인 경우 등록일 +1년을 만료일로 설정
* 방문횟수가 1 이상인 경우 최종이용일 +1년을 만료일로 설정
*/
include_once ('./_common.php');
include_once (FG_MANAGER_PATH.'/head.php');
if(!$_SESSION['user_id']) {
header('Location: '.FG_MANAGER_URL);
exit;
}
// 권한 체크 (관리자 이상만 가능)
if($_SESSION['user_lv'] < 3) {
die('권한이 없습니다.');
}
$isDebug = false; // 디버그 출력용 변수
$result_message = "";
$result_data = array();
$is_executed = false;
// AJAX 요청 처리
if(isset($_POST['ajax_mode'])) {
$ajax_mode = trim($_POST['ajax_mode']);
if ($ajax_mode === "bulk_set_expire_date") {
$status = isset($_POST['status']) ? trim($_POST['status']) : "정상";
$gr_id = isset($_POST['gr_id']) ? trim($_POST['gr_id']) : "";
// 검색 조건 만들기
$where = " WHERE status='{$status}'";
if (!empty($gr_id)) {
$where .= " AND gr_id='{$gr_id}'";
}
$squery = "SELECT * FROM {$fg['vip_list_table']}{$where}";
$result_list = sql_query($squery);
$updated_count = 0;
$error_count = 0;
$datetime = date("Y-m-d H:i:s");
while($list = sql_fetch_array($result_list)) {
$ent_count = $list['ent_count'];
// 만료일 설정 로직
if ($ent_count == 0) {
// 방문횟수가 0: 등록일 + 1년
$vip_date = date("Y-m-d", strtotime($list['join_datetime'] . " +1 year"));
} else {
// 방문횟수가 1 이상: 최종이용일 + 1년
$vip_date = date("Y-m-d", strtotime($list['last_ent_date'] . " +1 year"));
}
// 만료 여부 확인 (만료일이 오늘 이전이면 상태를 '만료'로 변경)
$today = date('Y-m-d');
$new_status = (strtotime($vip_date) < strtotime($today)) ? '만료' : '정상';
// DB 업데이트
$updateQuery = "UPDATE {$fg['vip_list_table']} SET vip_date='{$vip_date}', status='{$new_status}' WHERE idx='{$list['idx']}'";
$update_result = sql_query($updateQuery);
if ($update_result) {
$updated_count++;
} else {
$error_count++;
}
// log 기록
$work = "VIP만료일일괄설정";
$work_detail = "카드번호 : ".$list['vip_card_no']." 만료일 : ".$vip_date." 상태 : ".$new_status." 처리자 : ".$_SESSION['user_name'];
$logUpdate = log_update($work, $work_detail, $_SESSION['user_id'], $datetime);
}
$data = array(
"isSuccess" => true,
"updated_count" => $updated_count,
"error_count" => $error_count
);
header("Content-Type: application/json");
echo json_encode($data);
exit;
}
}
// 1회성 실행 모드 (GET/POST 쿼리 파라미터)
if(isset($_REQUEST['confirm']) && $_REQUEST['confirm'] == 'yes') {
$datetime = date("Y-m-d H:i:s");
$is_executed = true;
// 모든 VIP 정상 상태 데이터 조회
$squery = "SELECT * FROM {$fg['vip_list_table']} WHERE status='정상'";
$result_list = sql_query($squery);
$updated_count = 0;
$error_count = 0;
$details = array();
while($list = sql_fetch_array($result_list)) {
$ent_count = $list['ent_count'];
// 만료일 설정 로직
if ($ent_count == 0) {
// 방문횟수가 0: 등록일 + 1년
$vip_date = date("Y-m-d", strtotime($list['join_datetime'] . " +1 year"));
$logic_type = "등록일 기준";
} else {
// 방문횟수가 1 이상: 최종이용일 + 1년
$vip_date = date("Y-m-d", strtotime($list['last_ent_date'] . " +1 year"));
$logic_type = "최종이용일 기준";
}
// 만료 여부 확인 (만료일이 오늘 이전이면 상태를 '만료'로 변경)
$today = date('Y-m-d');
$new_status = (strtotime($vip_date) < strtotime($today)) ? '만료' : '정상';
// DB 업데이트
$updateQuery = "UPDATE {$fg['vip_list_table']} SET vip_date='{$vip_date}', status='{$new_status}' WHERE idx='{$list['idx']}'";
$update_result = sql_query($updateQuery);
if ($update_result) {
$updated_count++;
$details[] = array(
'card_no' => $list['vip_card_no'],
'name' => $list['vip_name'],
'old_date' => $list['vip_date'],
'new_date' => $vip_date,
'logic' => $logic_type,
'ent_count' => $ent_count,
'new_status' => $new_status,
'status_changed' => ($new_status !== $list['status']) ? 'O' : 'X'
);
} else {
$error_count++;
}
// log 기록
$work = "VIP만료일일괄설정";
$work_detail = "카드번호 : ".$list['vip_card_no']." 만료일 : ".$vip_date." (" . $logic_type . ") 상태 : ".$new_status." 처리자 : ".$_SESSION['user_name'];
$logUpdate = log_update($work, $work_detail, $_SESSION['user_id'], $datetime);
}
$result_message = "처리 완료: 업데이트 성공 {$updated_count}건, 실패 {$error_count}";
$result_data = $details;
}
?>
<style>
.expire-date-container {
max-width: 900px;
margin: 20px auto;
}
.result-table {
font-size: 12px;
}
.result-table td {
padding: 8px;
}
.success-bg {
background-color: #d4edda;
}
.error-bg {
background-color: #f8d7da;
}
</style>
<div class="expire-date-container">
<h2 class="mb-4">VIP 만료일 일괄 설정</h2>
<?php if($is_executed) { ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>✓ 처리 완료!</strong>
<?= $result_message ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php if(count($result_data) > 0) { ?>
<div class="card mt-4">
<div class="card-header">
<h5>처리 결과 상세</h5>
</div>
<div class="card-body">
<table class="table table-sm result-table">
<thead>
<tr>
<th>카드번호</th>
<th>성명</th>
<th>이전 만료일</th>
<th>신규 만료일</th>
<th>설정 기준</th>
<th>방문횟수</th>
<th>신규 상태</th>
<th>상태변경</th>
</tr>
</thead>
<tbody>
<?php foreach($result_data as $item) { ?>
<tr class="success-bg">
<td><?= $item['card_no'] ?></td>
<td><?= $item['name'] ?></td>
<td><?= ($item['old_date'] == '9999-12-31') ? '평생' : $item['old_date'] ?></td>
<td><strong><?= $item['new_date'] ?></strong></td>
<td><?= $item['logic'] ?></td>
<td><?= $item['ent_count'] ?></td>
<td><?= $item['new_status'] ?></td>
<td><?= ($item['status_changed'] === 'O') ? '<span class="badge bg-warning">변경됨</span>' : '-' ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<?php } ?>
<div class="mt-4">
<a href="vip_list.php" class="btn btn-primary">VIP 목록으로 돌아가기</a>
</div>
<?php } else { ?>
<div class="card">
<div class="card-body">
<h5 class="card-title">작업 설명</h5>
<ul>
<li><strong>상태: 정상</strong>인 모든 VIP의 만료일을 설정합니다</li>
<li><strong>방문횟수가 0</strong>이면: <mark>등록일 + 1년</mark>을 만료일로 설정</li>
<li><strong>방문횟수가 1 이상</strong>이면: <mark>최종이용일 + 1년</mark>을 만료일로 설정</li>
<li>모든 변경사항은 로그에 기록됩니다</li>
</ul>
</div>
</div>
<div class="alert alert-warning mt-4" role="alert">
<strong>⚠️ 주의:</strong> 이 작업은 취소할 수 없습니다.
<br>현재 상태의 모든 정상 상태 VIP <?php
$check_count = get_num_rows("{$fg['vip_list_table']}", "WHERE status='정상'");
echo $check_count;
?>건의 만료일이 변경됩니다.
</div>
<div class="mt-4">
<form method="post" style="display: inline;">
<button type="submit" name="confirm" value="yes" class="btn btn-danger btn-lg">
<i class="fa-solid fa-exclamation-triangle"></i> 실행
</button>
</form>
<a href="vip_list.php" class="btn btn-secondary btn-lg">취소</a>
</div>
<?php } ?>
</div>
<?php include_once FG_MANAGER_PATH.'/tail.php';

View File

@ -1499,8 +1499,8 @@ function pay_approval()
break;
}
f.method.value = pay_method;
f.orderId.value = '<?=$od_id?>';
f.orderName.value = '<?=$goods?>';
f.orderId.value = "<?php echo $od_id; ?>";
f.orderName.value = "<?php echo $goods; ?>";
f.customerName.value = pf.od_name.value;
f.customerEmail.value = pf.od_email.value;
@ -1523,6 +1523,10 @@ function pay_approval()
f.amountCurrency.value = 'KRW';
f.amountValue.value = f.good_mny.value;
if (pf && pf.amountValue) {
pf.amountValue.value = f.good_mny.value;
}
<?php if($default['de_tax_flag_use']) { ?>
f.taxFreeAmount.value = pf.comm_free_mny.value;
<?php } ?>

View File

@ -183,7 +183,7 @@ if((int)$pp['pp_price'] !== (int)$pg_price) {
include G5_SHOP_PATH.'/lg/xpay_cancel.php';
break;
case 'toss':
include G5_SHOP_PATH.'/toss/toss_result.php';
include G5_SHOP_PATH.'/toss/toss_cancel.php';
break;
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';
@ -271,7 +271,7 @@ if($pp_receipt_price > 0 && $pp['pp_id'] && $pp['od_id']) {
include G5_SHOP_PATH.'/lg/xpay_cancel.php';
break;
case 'toss':
include G5_SHOP_PATH.'/toss/toss_result.php';
include G5_SHOP_PATH.'/toss/toss_cancel.php';
break;
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';

View File

@ -90,7 +90,7 @@ foreach($payReqMap as $key => $value) {
* 수정불가.
*/
const clientKey = "<?php echo $config['cf_toss_client_key']; ?>";
const customerKey = "<?php echo isset($member['mb_id']) ? $member['mb_id'] : ''; ?>";
const customerKey = "<?php echo $is_member ? $member['mb_id'] : md5(get_session('ss_order_id')); ?>";
const tossPayments = TossPayments(clientKey);
const payment = tossPayments.payment({ customerKey });

View File

@ -3,6 +3,8 @@ include_once('./_common.php');
include_once(G5_SHOP_PATH.'/settle_naverpay.inc.php');
include_once(G5_LIB_PATH.'/naverpay.lib.php');
if (!(defined('G5_SHOP_USE_NAVERPAY') && G5_SHOP_USE_NAVERPAY)) return;
$pattern = '#[/\'\"%=*\#\(\)\|\+\&\!\$~\{\}\[\]`;:\?\^\,]#';
$post_naverpay_form = isset($_POST['naverpay_form']) ? clean_xss_tags($_POST['naverpay_form']) : '';
@ -98,7 +100,8 @@ for($i=0; $i<$count; $i++) {
$opt_count = (isset($_POST['io_id'][$it_id]) && is_array($_POST['io_id'][$it_id])) ? count($_POST['io_id'][$it_id]) : 0;
if( ! $it_id) continue;
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $it_id)) continue;
if($opt_count && $_POST['io_type'][$it_id][0] != 0)
return_error2json('상품의 선택옵션을 선택해 주십시오.');

View File

@ -3,6 +3,8 @@ include_once('./_common.php');
include_once(G5_SHOP_PATH.'/settle_naverpay.inc.php');
include_once(G5_LIB_PATH.'/naverpay.lib.php');
if (!(defined('G5_SHOP_USE_NAVERPAY') && G5_SHOP_USE_NAVERPAY)) return;
$count = (isset($_POST['it_id']) && is_array($_POST['it_id'])) ? count($_POST['it_id']) : 0;
if ($count < 1)
@ -13,6 +15,8 @@ $item = '';
for($i=0; $i<$count; $i++) {
$it_id = isset($_POST['it_id']) ? $_POST['it_id'][$i] : '';
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $it_id)) continue;
// 상품정보
$it = get_shop_item($it_id, true);

View File

@ -410,13 +410,13 @@ if($od['od_pg'] == 'lg') {
// 현금영수증 발급을 사용하는 경우에만
if ((function_exists('shop_is_taxsave') && shop_is_taxsave($od)) || (function_exists('is_order_cashreceipt') && is_order_cashreceipt($od))) {
// 미수금이 없고 현금일 경우에만 현금영수증을 발급 할 수 있습니다.
if ($misu_price == 0 && is_order_cashreceipt($od)) {
if ($misu_price == 0) {
?>
<tr>
<th scope="row">현금영수증</th>
<td>
<?php
if ($od['od_cash'])
if ($od['od_cash'] && is_order_cashreceipt($od))
{
if($od['od_pg'] == 'lg') {
require_once G5_SHOP_PATH.'/settle_lg.inc.php';

View File

@ -15,6 +15,8 @@ if(basename($_SERVER['SCRIPT_NAME']) == 'item.php') {
return;
}
define('G5_SHOP_USE_NAVERPAY', 1);
$naverpay_button_js = '';
$is_mobile_order = is_mobile();

View File

@ -13,7 +13,7 @@ if($default['de_iche_use'] || $default['de_vbank_use'] || $default['de_hp_use']
* 수정불가.
*/
const clientKey = "<?php echo $config['cf_toss_client_key']; ?>";
const customerKey = "<?php echo isset($member['mb_id']) ? $member['mb_id'] : ''; ?>";
const customerKey = "<?php echo $is_member ? $member['mb_id'] : md5(get_session('ss_order_id')); ?>";
const tossPayments = TossPayments(clientKey);
const payment = tossPayments.payment({ customerKey });

View File

@ -16,9 +16,9 @@ $row = sql_fetch($sql);
$data = isset($row['dt_data']) ? unserialize(base64_decode($row['dt_data'])) : array();
$amount = isset($data['amountValue']) ? $data['amountValue'] : 0;
$amount = isset($data['amountValue']) ? (int)$data['amountValue'] : 0;
if ($amount <= 0) {
if ($amount <= 0 || $amount !== (int)$order_price) {
alert('결제금액이 올바르지 않습니다.', G5_SHOP_URL);
}

View File

@ -536,13 +536,13 @@ if($od['od_pg'] == 'lg') {
// 현금영수증 발급을 사용하는 경우 또는 현금영수증 발급을 한 주문건이면
if ((function_exists('shop_is_taxsave') && shop_is_taxsave($od)) || (function_exists('is_order_cashreceipt') && is_order_cashreceipt($od))) {
// 미수금이 없고 현금일 경우에만 현금영수증을 발급 할 수 있습니다.
if ($misu_price == 0 && is_order_cashreceipt($od)) {
if ($misu_price == 0) {
?>
<li>
<strong class="letter-2px">현금영수증</strong>
<span>
<?php
if ($od['od_cash'])
if ($od['od_cash'] && is_order_cashreceipt($od))
{
if($od['od_pg'] == 'lg') {
require_once G5_SHOP_PATH.'/settle_lg.inc.php';

View File

@ -2,7 +2,7 @@
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
define('G5_VERSION', '그누보드5');
define('G5_GNUBOARD_VER', '5.6.23');
define('G5_GNUBOARD_VER', '5.6.24');
// 그누보드5.4.5.5 버전과 영카트5.4.5.5.1 버전을 합쳐서 그누보드5.4.6 버전에서 시작함 (kagla-210617)
// G5_YOUNGCART_VER 이 상수를 사용하는 곳이 있으므로 주석 처리 해제함
// 그누보드5.4.6 이상 버전 부터는 영카트를 그누보드에 포함하여 배포하므로 영카트5의 버전은 의미가 없습니다.