변경 파일 목록
총 209개
엑셀 다운로드 시 다운로드 기록 수집
ExcelRequest.phpComponent/Excel/애널리틱스 세션 분석 기능 고도화
Cart.phpComponent/Cart/RegularOrderCart.phpComponent/Cart/DBTableField.phpComponent/Database/ExternalOrder.phpComponent/Order/OrderAdminNew.phpComponent/Order/OrderAdmin.phpComponent/Order/OrderNew.phpComponent/Order/Order.phpComponent/Order/ReOrderCalculation.phpComponent/Order/Wish.phpComponent/Wish/MemberPsController.phpController/Front/Member/MemberPsController.phpController/Mobile/Member/개인정보 수집 및 이용 동의 템플릿 개정
excel_member_up.phpAdmin/member/member_detail_search.phpAdmin/member/member_joinitem.phpAdmin/member/member_modify.phpAdmin/member/member_register.phpAdmin/member/_member_view_app_device.phpAdmin/member/_member_view_business.phpAdmin/member/_member_view_history.phpAdmin/member/_member_view_other.phpAdmin/member/_member_view.phpAdmin/member/base_agreement_with_private.phpAdmin/policy/member_crm_detail.phpAdmin/share/BuyerInformCode.phpComponent/Agreement/BuyerInform.phpComponent/Agreement/BuyerInformVo.phpComponent/Agreement/DBTableField.phpComponent/Database/MemberTableField.phpComponent/Database/ExcelMember.phpComponent/Excel/History.phpComponent/Member/MemberAdmin.phpComponent/Member/MemberDAO.phpComponent/Member/Member.phpComponent/Member/MemberVO.phpComponent/Member/MyPage.phpComponent/Member/MemberUtil.phpComponent/Member/Util/MemberModifyController.phpController/Admin/Member/MemberPsController.phpController/Admin/Member/MemberRegisterController.phpController/Admin/Member/BaseAgreementWithPrivateController.phpController/Admin/Policy/BaseAgreementWithPrivatePsController.phpController/Admin/Policy/MemberCrmDetailController.phpController/Admin/Share/JoinAgreementController.phpController/Front/Member/LoginPsController.phpController/Front/Member/MyPageController.phpController/Front/Mypage/AgreementController.phpController/Front/Service/join_agreement.htmldata/skin/front/moment/member/_join_view.htmldata/skin/front/moment/member/_join_view_other.htmldata/skin/front/moment/member/my_page.htmldata/skin/front/moment/mypage/join_agreement.htmldata/skin/front/mygreek/member/_join_view.htmldata/skin/front/mygreek/member/_join_view_other.htmldata/skin/front/mygreek/member/my_page.htmldata/skin/front/mygreek/mypage/join_agreement.htmldata/skin/front/story_g/member/_join_view.htmldata/skin/front/story_g/member/_join_view_other.htmldata/skin/front/story_g/member/my_page.htmldata/skin/front/story_g/mypage/join_agreement.htmldata/skin/mobile/moment/member/_join_view.htmldata/skin/mobile/moment/member/_join_view_other.htmldata/skin/mobile/moment/member/my_page.htmldata/skin/mobile/moment/mypage/join_agreement.htmldata/skin/mobile/mygreek/member/_join_view.htmldata/skin/mobile/mygreek/member/_join_view_other.htmldata/skin/mobile/mygreek/member/my_page.htmldata/skin/mobile/mygreek/mypage/join_agreement.htmldata/skin/mobile/story_g/member/_join_view.htmldata/skin/mobile/story_g/member/_join_view_other.htmldata/skin/mobile/story_g/member/my_page.htmldata/skin/mobile/story_g/mypage/지역별 추가배송비 구간별 반복 부과 옵션 추가
delivery_regist.phpAdmin/policy/delivery_regist.phpAdmin/provider/policy/Cart.phpComponent/Cart/DBTableField.phpComponent/Database/DeliveryCart.phpComponent/Delivery/Delivery.phpComponent/Delivery/DeliveryRegistController.phpController/Admin/Policy/layer.cssdata/skin/front/moment/css/common/layer/goods_view.htmldata/skin/front/moment/goods/layer_option.htmldata/skin/front/moment/goods/layer.cssdata/skin/front/mygreek/css/common/layer/goods_view.htmldata/skin/front/mygreek/goods/layer_option.htmldata/skin/front/mygreek/goods/icon_warning_green.svgdata/skin/front/mygreek/img/icon/etc/gd_share.cssdata/skin/front/story_g/css/goods_view.htmldata/skin/front/story_g/goods/layer_option.htmldata/skin/front/story_g/goods/goods_view.htmldata/skin/mobile/moment/goods/goods_view.htmldata/skin/mobile/mygreek/goods/goods_view.htmldata/skin/mobile/story_g/goods/디자인 에디터 사용 이력 수집 기능 추가
layout_design_editor.phpAdmin/LMS 메시지 발송 시 제목 입력 기능
auto_send_config_recipient_section.phpAdmin/crm/auto_send_config/auto_send_config.phpAdmin/crm/crm_recipe_send.phpAdmin/crm/layer_preview_auto_send.phpAdmin/crm/layer_template_contents_sms.phpAdmin/crm/message_template_register.phpAdmin/crm/template_contents_sms.phpAdmin/crm/message_template_register/layer_member_sms_history_result.phpAdmin/crm/mobile_message_history/layer_sms_contents.phpAdmin/crm/mobile_message_history/layer_sms_history_result.phpAdmin/crm/mobile_message_history/layer_kakao_alimtalk_content_setting.phpAdmin/crm/mobile_send/layer_kakao_friendtalk_content_setting.phpAdmin/crm/mobile_send/layer_mobile_send_save_sms_template.phpAdmin/crm/mobile_send/layer_mobile_send_sms_template.phpAdmin/crm/mobile_send/layer_mobile_send_sms_template_result.phpAdmin/crm/mobile_send/layer_myapp_push_content_setting.phpAdmin/crm/mobile_send/layer_send_method_setting.phpAdmin/crm/mobile_send/layer_sms_content_setting.phpAdmin/crm/mobile_send/mobile_send.phpAdmin/crm/layer_preview_mobile_send_alternative.phpAdmin/crm/preview_mobile_send/layer_preview_mobile_send_sms.phpAdmin/crm/preview_mobile_send/sms_auto.phpAdmin/member/sms_log.phpAdmin/member/sms_send.phpAdmin/member/cart_remind_regist.phpAdmin/promotion/comeback_coupon_regist.phpAdmin/promotion/layer_cart_remind_message.phpAdmin/promotion/layer_comeback_coupon_sms.phpAdmin/share/layer_standby_sms.phpAdmin/share/member_crm_sms.phpAdmin/share/CartRemind.phpComponent/CartRemind/CouponAdmin.phpComponent/Coupon/DBTableField.phpComponent/Database/SmsAdmin.phpComponent/Sms/SmsAuto.phpComponent/Sms/SmsSender.phpComponent/Sms/LayerPreviewMobileSendController.phpController/Admin/Crm/LayerKakaoFriendtalkContentSettingController.phpController/Admin/Crm/MobileSend/LayerMobileSendSaveSmsTemplateController.phpController/Admin/Crm/MobileSend/LayerMyappPushContentSettingController.phpController/Admin/Crm/MobileSend/LayerSmsContentSettingController.phpController/Admin/Crm/MobileSend/SmsTemplatePsController.phpController/Admin/Crm/Sms/SmsAutoController.phpController/Admin/Member/SmsLogPsController.phpController/Admin/Member/SmsSendController.phpController/Admin/Member/CartRemindRegistController.phpController/Admin/Promotion/ComebackCouponRegistController.phpController/Admin/Promotion/LayerCartRemindMessageController.phpController/Admin/Promotion/LayerStandbySmsController.phpController/Admin/Share/무통장 입금은행 보안 강화.
OrderAdminNew.phpComponent/Order/OrderAdmin.phpComponent/Order/OrderNew.phpComponent/Order/Order.phpComponent/Order/무료보안 관리자 화면 안정성 개선
SecureSocketLayer.phpComponent/SiteLink/디자인 스킨 업로드 기능 개선
owned_skin_list_section.phpAdmin/design/design_skin_list/design_skin_list.phpAdmin/design/DesignSkinListController.phpController/Admin/Design/해외 상점 도메인 정보 표시 개선.
base_seo.phpAdmin/policy/Mall.phpComponent/Mall/BaseInfoController.phpController/Admin/Policy/BaseSeoController.phpController/Admin/Policy/본인인증(아이핀) 페이지 보안 강화
IpinApplyController.phpController/Front/Member/Ipin/IpinResultController.phpController/Front/Member/Ipin/IpinApplyController.phpController/Mobile/Member/Ipin/본인인증(아이핀) 페이지 보안 강화
IpinMainController.phpController/Front/Member/Ipin/자동메일 발송설정 게시판 선택 기능 개선.
AutoSendConfigController.phpController/Admin/Crm/AutoSendController.phpController/Admin/Crm/CrmRecipeSendController.phpController/Admin/Crm/IndexController.phpController/Admin/Crm/MailGateBridgeController.phpController/Admin/Crm/MailGateController.phpController/Admin/Crm/MailSendController.phpController/Admin/Crm/MailSendReceiveRefuseCountController.phpController/Admin/Crm/MessageConfigController.phpController/Admin/Crm/MessageTemplateController.phpController/Admin/Crm/MessageTemplateRegisterController.phpController/Admin/Crm/MobileHistoryController.phpController/Admin/Crm/MobileHistoryListController.phpController/Admin/Crm/MobileSendController.phpController/Admin/Crm/PopupChargeMessagePointsController.phpController/Admin/Crm/PopupManageCallNumberController.phpController/Admin/Crm/PopupSelectMembersController.phpController/Admin/Crm/정기배송 결제카드 등록 후 표시 개선.
regular_order.htmldata/skin/front/moment/order/regular_order.htmldata/skin/front/mygreek/order/regular_order.htmldata/skin/front/story_g/order/상품 검색 보안 강화.
Goods.phpComponent/Goods/사업자 회원 비활성화 시 회원정보 수정 프로세스 개선
MyPage.phpComponent/Member/MyPagePsController.phpController/Front/Mypage/gd_member2.jsdata/skin/front/moment/js/gd_member2.jsdata/skin/front/mygreek/js/gd_member2.jsdata/skin/front/story_g/js/gd_member2.jsdata/skin/mobile/moment/js/gd_member2.jsdata/skin/mobile/mygreek/js/gd_member2.jsdata/skin/mobile/story_g/js/카카오 간편 로그인 설정 안정성 개선
kakao_login_config.phpAdmin/member/KakaoLoginConfigController.phpController/Admin/Member/메타 전환 이벤트 중복집계 개선
OrderEndController.phpController/Front/Order/OrderEndController.phpController/Mobile/Order/관리자-유저 세션 격리 강화
MemberSnsDAO.phpComponent/Member/모바일 메시지 발송 엑셀 업로드 시 name 치환코드 적용
layer_preview_mobile_send.phpAdmin/crm/layer_send_method_setting.phpAdmin/crm/mobile_send/ExcelSms.phpComponent/Excel/회원 등급 평가 스케줄러 개선
CouponAdmin.phpComponent/Coupon/MemberTableField.phpComponent/Database/AppraisalMailSender.phpComponent/Member/Group/Appraisal.phpComponent/Member/Group/AppraisalSearch.phpComponent/Member/Group/GroupDomain.phpComponent/Member/Group/History.phpComponent/Member/MemberGroupPsController.phpController/Admin/Member/변경 파일 코드
추가삭제
변경 전ExcelRequest.php
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\StringUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Security\Token; | |
| use LogHandler; | |
| use Origin\Enum\RegularDelivery\RegularGoods\DeliveryCycle; | |
| use Request; | |
| use Session; | |
| $orderDelete->deleteLapseOrderExcelFormUpdate($arrData['requestSno'], $arrData['sno']); | |
| $this->_logger->channel('orderDelete')->info(__METHOD__ . ' ORDER DELETE EXCEL FORM SNO SAVE, DB_EXCEL_REQUEST INSERT NO : ' . $arrData['requestSno'] . ', EXCEL FORM SNO : ', [$arrData['formSno']]); | |
| return $arrData['requestSno']; | |
| } | |
| unset($arrBind); | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| return ['getData' => $setData, 'totalCount' => '$totalNum']; | |
| } | |
| } | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\StringUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Security\Token; | |
| use LogHandler; | |
| use Origin\Enum\RegularDelivery\RegularGoods\DeliveryCycle; | |
| use Request; | |
| use Session; | |
| $orderDelete->deleteLapseOrderExcelFormUpdate($arrData['requestSno'], $arrData['sno']); | |
| $this->_logger->channel('orderDelete')->info(__METHOD__ . ' ORDER DELETE EXCEL FORM SNO SAVE, DB_EXCEL_REQUEST INSERT NO : ' . $arrData['requestSno'] . ', EXCEL FORM SNO : ', [$arrData['formSno']]); | |
| return $arrData['requestSno']; | |
| } | |
| unset($arrBind); | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| return ['getData' => $setData, 'totalCount' => '$totalNum']; | |
| } | |
| } | |
변경 후ExcelRequest.php
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\ProducerUtils; | |
| use Framework\Utility\StringUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Security\Token; | |
| use Framework\Debug\Exception\MissingRequiredFieldException; | |
| use LogHandler; | |
| use Origin\DTO\Kafka\ShopDataExtractLogDTO; | |
| use Origin\Enum\Excel\ShopDataExtractTarget; | |
| use Origin\Enum\RegularDelivery\RegularGoods\DeliveryCycle; | |
| use Request; | |
| use Session; | |
| $orderDelete->deleteLapseOrderExcelFormUpdate($arrData['requestSno'], $arrData['sno']); | |
| $this->_logger->channel('orderDelete')->info(__METHOD__ . ' ORDER DELETE EXCEL FORM SNO SAVE, DB_EXCEL_REQUEST INSERT NO : ' . $arrData['requestSno'] . ', EXCEL FORM SNO : ', [$arrData['formSno']]); | |
| $this->publishExtractLog($formData, true, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return $arrData['requestSno']; | |
| } | |
| unset($arrBind); | |
| $this->publishExtractLog($formData, true, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return true; | |
| } else { | |
| $this->publishExtractLog($formData, false, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return false; | |
| } | |
| return ['getData' => $setData, 'totalCount' => '$totalNum']; | |
| } | |
| /** | |
| * 상점 데이터 추출 완료 결과를 카프카 토픽으로 발행한다. | |
| * | |
| * @param ?array $formData 엑셀 양식 데이터 (es_excelForm, menu 포함) | |
| * @param bool $isSuccess 추출 성공 여부 | |
| * @param string $extractType 추출 유형 (ShopDataExtractLogDTO::EXTRACT_TYPE_* 상수) | |
| * @return void | |
| */ | |
| protected function publishExtractLog(?array $formData, bool $isSuccess, string $extractType): void | |
| { | |
| try { | |
| $godosno = Globals::get('gLicense.godosno'); | |
| if (empty($godosno)) { | |
| throw new MissingRequiredFieldException('상점 데이터 추출 로그 발행 실패: 라이선스 상점번호(godosno)가 없습니다.'); | |
| } | |
| $menu = $formData['menu'] ?? null; | |
| if (empty($menu)) { | |
| throw new MissingRequiredFieldException('상점 데이터 추출 로그 발행 실패: 엑셀 양식 메뉴(menu)가 없습니다.'); | |
| } | |
| $extractTarget = ShopDataExtractTarget::fromMenu($menu); | |
| // 매핑 미확정 메뉴(orderDraft, plusreview, adminLog)는 발행하지 않고 건너뛴다. (9월 배포 추가작업 예정) | |
| if ($extractTarget === null) { | |
| $this->_logger->channel('excel')->info( | |
| '상점 데이터 추출 로그 발행 생략: 매핑되지 않은 엑셀 양식 메뉴', | |
| [ | |
| 'godoSno' => (int)$godosno, | |
| 'extractType' => $extractType, | |
| 'extractTarget' => $extractTarget->value, | |
| 'isSuccess' => $isSuccess | |
| ] | |
| ); | |
| return; | |
| } | |
| $producer = new ProducerUtils(); | |
| $shopDataExtractLogDto = new ShopDataExtractLogDTO( | |
| [(int)$godosno], | |
| $extractType, | |
| $extractTarget->value, | |
| $isSuccess | |
| ); | |
| $producer->send( | |
| $producer::TOPIC_SHOP_DATA_EXTRACT_LOG_CREATE, | |
| json_encode($shopDataExtractLogDto->toArray()), | |
| $producer::MODE_RESULT_CALLLBACK | |
| ); | |
| } catch (\Throwable $e) { | |
| $this->_logger->channel('excel')->warning( | |
| '상점 데이터 추출 로그 카프카 메시지 발송 실패', | |
| [ | |
| 'exception' => $e, | |
| 'extractType' => $extractType, | |
| 'menu' => $formData['menu'] ?? null | |
| ] | |
| ); | |
| } | |
| } | |
| } | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\ProducerUtils; | |
| use Framework\Utility\StringUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Security\Token; | |
| use Framework\Debug\Exception\MissingRequiredFieldException; | |
| use LogHandler; | |
| use Origin\DTO\Kafka\ShopDataExtractLogDTO; | |
| use Origin\Enum\RegularDelivery\RegularGoods\DeliveryCycle; | |
| use Request; | |
| use Session; | |
| $orderDelete->deleteLapseOrderExcelFormUpdate($arrData['requestSno'], $arrData['sno']); | |
| $this->_logger->channel('orderDelete')->info(__METHOD__ . ' ORDER DELETE EXCEL FORM SNO SAVE, DB_EXCEL_REQUEST INSERT NO : ' . $arrData['requestSno'] . ', EXCEL FORM SNO : ', [$arrData['formSno']]); | |
| $this->publishExtractLog($arrData, true, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return $arrData['requestSno']; | |
| } | |
| unset($arrBind); | |
| $this->publishExtractLog($arrData, true, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return true; | |
| } else { | |
| $this->publishExtractLog($arrData, false, ShopDataExtractLogDTO::EXTRACT_TYPE_EXCEL); | |
| return false; | |
| } | |
| return ['getData' => $setData, 'totalCount' => '$totalNum']; | |
| } | |
| /** | |
| * 상점 데이터 추출 완료 결과를 카프카 토픽으로 발행한다. | |
| * | |
| * @param array $arrData 추출 요청 데이터 (menu 포함) | |
| * @param bool $isSuccess 추출 성공 여부 | |
| * @param string $extractType 추출 유형 (ShopDataExtractLogDTO::EXTRACT_TYPE_* 상수) | |
| * @return void | |
| */ | |
| protected function publishExtractLog(array $arrData, bool $isSuccess, string $extractType): void | |
| { | |
| try { | |
| $godosno = Globals::get('gLicense.godosno'); | |
| if (empty($godosno)) { | |
| throw new MissingRequiredFieldException('상점 데이터 추출 로그 발행 실패: 라이선스 상점번호(godosno)가 없습니다.'); | |
| } | |
| $extractTarget = $arrData['menu'] ? strtoupper($arrData['menu']) : null; | |
| $producer = new ProducerUtils(); | |
| $shopDataExtractLogDto = new ShopDataExtractLogDTO( | |
| [(int)$godosno], | |
| $extractType, | |
| $extractTarget, | |
| $isSuccess | |
| ); | |
| $producer->send( | |
| $producer::TOPIC_SHOP_DATA_EXTRACT_LOG_CREATE, | |
| json_encode($shopDataExtractLogDto->toArray()), | |
| $producer::MODE_RESULT_CALLLBACK | |
| ); | |
| } catch (\Throwable $e) { | |
| $this->_logger->channel('excel')->warning( | |
| '상점 데이터 추출 로그 카프카 메시지 발송 실패', | |
| [ | |
| 'exception' => $e, | |
| 'extractType' => $extractType, | |
| 'extractTarget' => $arrData['menu'] ?? null | |
| ] | |
| ); | |
| } | |
| } | |
| } | |
변경 전Cart.php
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Utility\ProducerUtils; | |
| use Framework\Utility\SkinUtils; | |
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| $result = $kafka->send($kafka::TOPIC_CART_ADD_STATISTICS, $kafka->makeData([$cartStatistics], 'cas'), $kafka::MODE_RESULT_CALLLBACK, true); | |
| \Logger::channel('kafka')->info('process sendMQ - return :', $result); | |
| } | |
| // 장바구니 변경 갯수 상품 업데이트 | |
| $goods = \App::load(\Component\Goods\Goods::class); | |
| $goods->setCartGoodsCount($arrData['goodsNo']); | |
변경 후Cart.php
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Framework\Utility\ProducerUtils; | |
| use Origin\Service\Statistics\Analytics\Cart\CartAddHistoryAnalyticsCollectorService; | |
| use Framework\Utility\SkinUtils; | |
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| $result = $kafka->send($kafka::TOPIC_CART_ADD_STATISTICS, $kafka->makeData([$cartStatistics], 'cas'), $kafka::MODE_RESULT_CALLLBACK, true); | |
| \Logger::channel('kafka')->info('process sendMQ - return :', $result); | |
| } | |
| // 장바구니 추가 통계 수집 (수기주문 제외) | |
| try { | |
| $cartAddHistoryAnalyticsCollectorService = \App::getInstance(CartAddHistoryAnalyticsCollectorService::class); | |
| if ($cartAddHistoryAnalyticsCollectorService->isCollectableCart($this->isWrite)) { | |
| $cartAddHistoryAnalyticsCollectorService->collectAnalytics($arrData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 장바구니 변경 갯수 상품 업데이트 | |
| $goods = \App::load(\Component\Goods\Goods::class); | |
| $goods->setCartGoodsCount($arrData['goodsNo']); | |
변경 전RegularOrderCart.php
| use Framework\Utility\Globals; | |
| use Repository\Goods\AddGoodsRepository; | |
| use Framework\Log\Logger; | |
| use Component\Policy\Policy; | |
| use Framework\Http\Request; | |
| use Component\Goods\Goods; | |
| // 장바구니 저장 | |
| $cartSno = $this->regularOrderCartRepository->saveCart($arrData); | |
| // 장바구니 변경 갯수 상품 업데이트 | |
| $goods = \App::load(\Component\Goods\Goods::class); | |
| $goods->setCartGoodsCount($arrData['goodsNo']); | |
변경 후RegularOrderCart.php
| use Framework\Utility\Globals; | |
| use Repository\Goods\AddGoodsRepository; | |
| use Framework\Log\Logger; | |
| use Origin\Service\Statistics\Analytics\Cart\CartAddHistoryAnalyticsCollectorService; | |
| use Component\Policy\Policy; | |
| use Framework\Http\Request; | |
| use Component\Goods\Goods; | |
| // 장바구니 저장 | |
| $cartSno = $this->regularOrderCartRepository->saveCart($arrData); | |
| // 장바구니 추가 통계 수집 | |
| try { | |
| $cartAddHistoryAnalyticsCollectorService = \App::getInstance(CartAddHistoryAnalyticsCollectorService::class); | |
| $cartAddHistoryAnalyticsCollectorService->collectAnalytics($arrData); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 장바구니 변경 갯수 상품 업데이트 | |
| $goods = \App::load(\Component\Goods\Goods::class); | |
| $goods->setCartGoodsCount($arrData['goodsNo']); | |
변경 전DBTableField.php
| * @author artherot | |
| * @return array order 테이블 필드 정보 | |
| */ | |
| public static function tableOrder() | |
| { | |
| // @formatter:off | |
변경 후DBTableField.php
| * @author artherot | |
| * @return array order 테이블 필드 정보 | |
| */ | |
| public static function tableAnalyticsOrder() | |
| { | |
| // @formatter:off | |
| $arrField = [ | |
| ['val' => 'orderNo', 'typ' => 's', 'def' => null], // 주문번호 | |
| ['val' => 'clientId', 'typ' => 's', 'def' => null], // 애널리틱스 클라이언트 ID | |
| ['val' => 'sessionId', 'typ' => 's', 'def' => null], // 애널리틱스 세션 ID | |
| ['val' => 'regDt', 'typ' => 's', 'def' => null], // 등록일 | |
| ]; | |
| // @formatter:on | |
| return $arrField; | |
| } | |
| public static function tableOrder() | |
| { | |
| // @formatter:off | |
변경 전ExternalOrder.php
| use Session; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\StringUtils; | |
| /** | |
| * 외부채널 주문 관련 class | |
| } | |
| unset($arrBind); | |
| } | |
| /* | |
변경 후ExternalOrder.php
| use Session; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\StringUtils; | |
| use Origin\Service\Statistics\Analytics\Order\AnalyticsOrderService; | |
| /** | |
| * 외부채널 주문 관련 class | |
| } | |
| unset($arrBind); | |
| // 애널리틱스 주문 추적값 저장 | |
| try { | |
| if (empty($insertDataOrder['orderNo'])) { | |
| throw new \InvalidArgumentException('orderNo가 비어있습니다'); | |
| } | |
| $analyticsOrderService = \App::getInstance(AnalyticsOrderService::class); | |
| $analyticsOrderService->saveAnalyticsOrder($insertDataOrder['orderNo']); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analyticsOrder 저장 실패', ['exception' => $e, 'errorMessage' => $e->getMessage(), 'orderNo' => $insertDataOrder['orderNo']]); | |
| } | |
| } | |
| /* | |
변경 전OrderAdminNew.php
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| use LogHandler; | |
| use Origin\Enum\Order\OrderSettleKind; | |
| use Origin\Enum\Order\OrderHandleMode; | |
| use Origin\Enum\Order\OrderStatusCode; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Repository\Order\OrderDeliveryOriginalRepository; | |
| break; | |
| } | |
| // 주문 완료 통계 수집 | |
| try { | |
| $isOrderAnalyticsCollectAvailable = false; | |
| $analyticsCheckChangeStatus = substr($changeStatus, 0, 1); | |
| if (in_array($analyticsCheckChangeStatus, ['p', 'o'])) { // 결제완료, 입금대기일때 | |
| if ($analyticsCheckChangeStatus === 'o' && in_array($orderData['settleKind'], OrderSettleKind::getVirtualAccountKinds())) { // 입금 대기중인 가상계좌는 수집 | |
| $isOrderAnalyticsCollectAvailable = true; | |
| } | |
| if ($analyticsCheckChangeStatus === 'p' && !in_array($orderData['settleKind'], OrderSettleKind::getBankAndVirtualAccountKinds())) { // 결제 완료된 무통장/가상계좌는 수집 하지 않음 | |
| $isOrderAnalyticsCollectAvailable = true; | |
| } | |
| } | |
| if ($isOrderAnalyticsCollectAvailable) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $orderNo, | |
| 'order' => $orderData, | |
| ]; | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // 고도몰 주문 웹훅 발송 | |
변경 후OrderAdminNew.php
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| use LogHandler; | |
| use Origin\Enum\Order\OrderHandleMode; | |
| use Origin\Enum\Order\OrderStatusCode; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Origin\Enum\Statistics\Analytics\Order\ClaimType; | |
| use Origin\Service\Statistics\Analytics\Order\ClaimCompleteAnalyticsCollectorService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Repository\Order\OrderDeliveryOriginalRepository; | |
| break; | |
| } | |
| try { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $claimCompleteStatisticsCollectorService = \App::getInstance(ClaimCompleteAnalyticsCollectorService::class); | |
| // 결제완료 묶음에 교환추가(z)가 섞이면 통째로 claim, 아니면 일반 결제완료(order_complete) | |
| $exchangeExtraPaymentAmount = $claimCompleteStatisticsCollectorService->getCollectibleExchangeExtraPaymentAmount($changeStatus, $orderNo, $bundleData['sno'] ?? []); | |
| if (!empty($exchangeExtraPaymentAmount)) { | |
| // 교환추가가 섞인 결제완료 → claim_complete 수집 (일반상품 결제금액 + 교환 차액) | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'claimType' => ClaimType::EXCHANGE->value, | |
| 'claimAmount' => $exchangeExtraPaymentAmount, | |
| ]); | |
| } elseif ($orderCompleteStatisticsCollectorService->isOrderCompleteCollectible($changeStatus)) { | |
| $orderCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'order' => $orderData, | |
| ]); | |
| } | |
| // 결제완료 → 입금대기 되돌림 시점 통계 수집 | |
| // 되돌림은 주문 묶음 전체 단위로만 일어나므로(부분 되돌림 없음) 대표로 첫 상품 상태만 확인 | |
| $prevStatus = array_values($goodsData)[0]['orderStatus'] ?? ''; | |
| $claimAmount = $orderData['settlePrice'] ?? 0; | |
| $mileageClaimAmount = $orderData['useMileage'] ?? 0; | |
| $depositClaimAmount = $orderData['useDeposit'] ?? 0; | |
| if ($claimCompleteStatisticsCollectorService->isReversalToWaitDepositCollectible($changeStatus, $prevStatus, (float)$claimAmount, (float)$mileageClaimAmount, (float)$depositClaimAmount)) { | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'claimType' => ClaimType::REVERSAL->value, | |
| 'claimAmount' => $claimAmount, | |
| 'mileageClaimAmount' => $mileageClaimAmount, | |
| 'depositClaimAmount' => $depositClaimAmount, | |
| ]); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 고도몰 주문 웹훅 발송 | |
변경 전OrderAdmin.php
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| use LogHandler; | |
| use Origin\Enum\Order\OrderSettleKind; | |
| use Origin\Enum\Order\OrderHandleMode; | |
| use Origin\Enum\Order\OrderStatusCode; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Repository\Order\OrderDeliveryOriginalRepository; | |
| break; | |
| } | |
| // 주문 완료 통계 수집 | |
| try { | |
| $isOrderAnalyticsCollectAvailable = false; | |
| $analyticsCheckChangeStatus = substr($changeStatus, 0, 1); | |
| if (in_array($analyticsCheckChangeStatus, ['p', 'o'])) { // 결제완료, 입금대기일때 | |
| if ($analyticsCheckChangeStatus === 'o' && in_array($orderData['settleKind'], OrderSettleKind::getVirtualAccountKinds())) { // 입금 대기중인 가상계좌는 수집 | |
| $isOrderAnalyticsCollectAvailable = true; | |
| } | |
| if ($analyticsCheckChangeStatus === 'p' && !in_array($orderData['settleKind'], OrderSettleKind::getBankAndVirtualAccountKinds())) { // 결제 완료된 무통장/가상계좌는 수집 하지 않음 | |
| $isOrderAnalyticsCollectAvailable = true; | |
| } | |
| } | |
| if ($isOrderAnalyticsCollectAvailable) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $orderNo, | |
| 'order' => $orderData, | |
| ]; | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // 고도몰 주문 웹훅 발송 | |
변경 후OrderAdmin.php
| use Framework\Utility\StringUtils; | |
| use Globals; | |
| use LogHandler; | |
| use Origin\Enum\Order\OrderHandleMode; | |
| use Origin\Enum\Order\OrderStatusCode; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Origin\Enum\Statistics\Analytics\Order\ClaimType; | |
| use Origin\Service\Statistics\Analytics\Order\ClaimCompleteAnalyticsCollectorService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Repository\Order\OrderDeliveryOriginalRepository; | |
| break; | |
| } | |
| try { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $claimCompleteStatisticsCollectorService = \App::getInstance(ClaimCompleteAnalyticsCollectorService::class); | |
| // 결제완료 묶음에 교환추가(z)가 섞이면 통째로 claim, 아니면 일반 결제완료(order_complete) | |
| $exchangeExtraPaymentAmount = $claimCompleteStatisticsCollectorService->getCollectibleExchangeExtraPaymentAmount($changeStatus, $orderNo, $bundleData['sno'] ?? []); | |
| if (!empty($exchangeExtraPaymentAmount)) { | |
| // 교환추가가 섞인 결제완료 → claim_complete 수집 (일반상품 결제금액 + 교환 차액) | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'claimType' => ClaimType::EXCHANGE->value, | |
| 'claimAmount' => $exchangeExtraPaymentAmount, | |
| ]); | |
| } elseif ($orderCompleteStatisticsCollectorService->isOrderCompleteCollectible($changeStatus)) { | |
| $orderCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'order' => $orderData, | |
| ]); | |
| } | |
| // 결제완료 → 입금대기 되돌림 시점 통계 수집 | |
| // 되돌림은 주문 묶음 전체 단위로만 일어나므로(부분 되돌림 없음) 대표로 첫 상품 상태만 확인 | |
| $prevStatus = array_values($goodsData)[0]['orderStatus'] ?? ''; | |
| $claimAmount = $orderData['settlePrice'] ?? 0; | |
| $mileageClaimAmount = $orderData['useMileage'] ?? 0; | |
| $depositClaimAmount = $orderData['useDeposit'] ?? 0; | |
| if ($claimCompleteStatisticsCollectorService->isReversalToWaitDepositCollectible($changeStatus, $prevStatus, (float)$claimAmount, (float)$mileageClaimAmount, (float)$depositClaimAmount)) { | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $orderNo, | |
| 'claimType' => ClaimType::REVERSAL->value, | |
| 'claimAmount' => $claimAmount, | |
| 'mileageClaimAmount' => $mileageClaimAmount, | |
| 'depositClaimAmount' => $depositClaimAmount, | |
| ]); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 고도몰 주문 웹훅 발송 | |
변경 전OrderNew.php
| use LogHandler; | |
| use Origin\Constants\WebHookEventType; | |
| use Origin\Service\Order\OrderInfoService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Request; | |
| $this->db->set_insert_db(DB_ORDER, $arrBind['param'], $arrBind['bind'], 'y', false); | |
| unset($arrBind); | |
| $this->setPayHistory($history); | |
| // 주문 사은품 정보 저장 | |
| } | |
| } | |
| // 주문 완료 통계 수집 | |
| try { | |
| if ($orderInfo['settleKind'] == 'gb' || $orderInfo['settleKind'] == self::SETTLE_KIND_ZERO) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $this->orderNo, | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // 주문서 저장 이후, channelType 세션 데이터 제거 | |
변경 후OrderNew.php
| use LogHandler; | |
| use Origin\Constants\WebHookEventType; | |
| use Origin\Service\Order\OrderInfoService; | |
| use Origin\Service\Statistics\Analytics\Order\AnalyticsOrderService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Request; | |
| $this->db->set_insert_db(DB_ORDER, $arrBind['param'], $arrBind['bind'], 'y', false); | |
| unset($arrBind); | |
| // 애널리틱스 주문 추적값 저장 | |
| try { | |
| if (empty($this->orderNo)) { | |
| throw new \InvalidArgumentException('orderNo가 비어있습니다'); | |
| } | |
| $analyticsOrderService = \App::getInstance(AnalyticsOrderService::class); | |
| $analyticsOrderService->saveAnalyticsOrder($this->orderNo); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analyticsOrder 저장 실패', ['exception' => $e, 'errorMessage' => $e->getMessage(), 'orderNo' => $this->orderNo]); | |
| } | |
| $this->setPayHistory($history); | |
| // 주문 사은품 정보 저장 | |
| } | |
| } | |
| // 결제완료 시점 통계 수집 | |
| try { | |
| if ($orderInfo['settleKind'] == self::SETTLE_KIND_ZERO) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $this->orderNo, | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 주문서 저장 이후, channelType 세션 데이터 제거 | |
변경 전Order.php
| use LogHandler; | |
| use Origin\Constants\WebHookEventType; | |
| use Origin\Service\Order\OrderInfoService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Origin\Enum\RegularDelivery\RegularOrder\RegularOrderStatus; | |
| $this->db->set_insert_db(DB_ORDER, $arrBind['param'], $arrBind['bind'], 'y', false); | |
| unset($arrBind); | |
| // 최초결제 결제히스토리 저장 | |
| $history = [ | |
| 'orderNo' => $this->orderNo,// 주문번호 | |
| } | |
| } | |
| // 주문 완료 통계 수집 | |
| try { | |
| if ($orderInfo['settleKind'] == 'gb' || $orderInfo['settleKind'] == self::SETTLE_KIND_ZERO) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $this->orderNo, | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // 페이스북 FBE v2 pixelCookie 값 주문서 저장 | |
변경 후Order.php
| use LogHandler; | |
| use Origin\Constants\WebHookEventType; | |
| use Origin\Service\Order\OrderInfoService; | |
| use Origin\Service\Statistics\Analytics\Order\AnalyticsOrderService; | |
| use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Origin\Enum\RegularDelivery\RegularOrder\RegularOrderStatus; | |
| $this->db->set_insert_db(DB_ORDER, $arrBind['param'], $arrBind['bind'], 'y', false); | |
| unset($arrBind); | |
| // 애널리틱스 주문 추적값 저장 | |
| try { | |
| if (empty($this->orderNo)) { | |
| throw new \InvalidArgumentException('orderNo가 비어있습니다'); | |
| } | |
| $analyticsOrderService = \App::getInstance(AnalyticsOrderService::class); | |
| $analyticsOrderService->saveAnalyticsOrder($this->orderNo); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analyticsOrder 저장 실패', ['exception' => $e, 'errorMessage' => $e->getMessage(), 'orderNo' => $this->orderNo]); | |
| } | |
| // 최초결제 결제히스토리 저장 | |
| $history = [ | |
| 'orderNo' => $this->orderNo,// 주문번호 | |
| } | |
| } | |
| // 결제완료 시점 통계 수집 | |
| try { | |
| if ($orderInfo['settleKind'] == self::SETTLE_KIND_ZERO) { | |
| $orderCompleteStatisticsCollectorService = \App::getInstance(OrderCompleteAnalyticsCollectorService::class); | |
| $orderAnalyticsData = [ | |
| 'orderNo' => $this->orderNo, | |
| $orderCompleteStatisticsCollectorService->collectAnalytics($orderAnalyticsData); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 페이스북 FBE v2 pixelCookie 값 주문서 저장 | |
변경 전ReOrderCalculation.php
| use Framework\Utility\NumberUtils; | |
| use Globals; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Session; | |
| use Origin\Traits\Logger\CommonLogStorageTrait; | |
| // 바로 위의 updateStatusPreprocess 는 내부에 transaction 이 한번 더 있기 때문에 이 exception 롤백과 무관하게 commit 됨. | |
| throw new Exception(__($returnError)); | |
| } | |
| } | |
| public function setRefundCompleteOrderGoodsNew($getData, $autoProcess = false, $userHandleFl = false) | |
| $presentConfirm = \App::getInstance(\Component\Present\Confirm\PresentConfirm::class); | |
| $presentConfirm->clearConfirmToken($getData['orderNo']); | |
| } | |
| } | |
| /** | |
| $this->orderWebHookService->sendOrderGoodsWebHook($webhookOrderGoodsSnos, $claimStatus, $changeStatus); | |
| } | |
| return true; | |
| } | |
변경 후ReOrderCalculation.php
| use Framework\Utility\NumberUtils; | |
| use Globals; | |
| use Origin\Service\WebHook\OrderWebHookService; | |
| use Origin\Enum\Statistics\Analytics\Order\ClaimType; | |
| use Origin\Service\Statistics\Analytics\Order\ClaimCompleteAnalyticsCollectorService; | |
| use Session; | |
| use Origin\Traits\Logger\CommonLogStorageTrait; | |
| // 바로 위의 updateStatusPreprocess 는 내부에 transaction 이 한번 더 있기 때문에 이 exception 롤백과 무관하게 commit 됨. | |
| throw new Exception(__($returnError)); | |
| } | |
| // 환불완료 시점 통계 수집 | |
| try { | |
| $claimCompleteStatisticsCollectorService = \App::getInstance(ClaimCompleteAnalyticsCollectorService::class); | |
| $claimAmount = $getData['check']['totalRefundPrice'] ?? 0; | |
| $mileageClaimAmount = gd_isset($getData['info']['refundGoodsUseMileage'], 0) + gd_isset($getData['info']['refundDeliveryUseMileage'], 0) - gd_isset($getData['info']['refundUseMileageCommission'], 0); | |
| $depositClaimAmount = gd_isset($getData['info']['refundGoodsUseDeposit'], 0) + gd_isset($getData['info']['refundDeliveryUseDeposit'], 0) - gd_isset($getData['info']['refundUseDepositCommission'], 0); | |
| if ($claimCompleteStatisticsCollectorService->isRefundAmountCollectible((float)$claimAmount, (float)$mileageClaimAmount, (float)$depositClaimAmount)) { | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $getData['orderNo'], | |
| 'claimType' => ClaimType::REFUND->value, | |
| 'claimAmount' => $claimAmount, | |
| 'mileageClaimAmount' => $mileageClaimAmount, | |
| 'depositClaimAmount' => $depositClaimAmount, | |
| ]); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| } | |
| public function setRefundCompleteOrderGoodsNew($getData, $autoProcess = false, $userHandleFl = false) | |
| $presentConfirm = \App::getInstance(\Component\Present\Confirm\PresentConfirm::class); | |
| $presentConfirm->clearConfirmToken($getData['orderNo']); | |
| } | |
| // 환불완료 시점 통계 수집 | |
| try { | |
| $claimCompleteStatisticsCollectorService = \App::getInstance(ClaimCompleteAnalyticsCollectorService::class); | |
| $claimAmount = $getData['check']['totalRefundPrice'] ?? 0; | |
| $mileageClaimAmount = gd_isset($getData['info']['refundGoodsUseMileage'], 0) + gd_isset($getData['info']['refundDeliveryUseMileage'], 0) - gd_isset($getData['info']['refundUseMileageCommission'], 0); | |
| $depositClaimAmount = gd_isset($getData['info']['refundGoodsUseDeposit'], 0) + gd_isset($getData['info']['refundDeliveryUseDeposit'], 0) - gd_isset($getData['info']['refundUseDepositCommission'], 0); | |
| if ($claimCompleteStatisticsCollectorService->isRefundAmountCollectible((float)$claimAmount, (float)$mileageClaimAmount, (float)$depositClaimAmount)) { | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $getData['orderNo'], | |
| 'claimType' => ClaimType::REFUND->value, | |
| 'claimAmount' => $claimAmount, | |
| 'mileageClaimAmount' => $mileageClaimAmount, | |
| 'depositClaimAmount' => $depositClaimAmount, | |
| ]); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| } | |
| /** | |
| $this->orderWebHookService->sendOrderGoodsWebHook($webhookOrderGoodsSnos, $claimStatus, $changeStatus); | |
| } | |
| // 교환접수 시점 통계 수집 | |
| try { | |
| $claimCompleteStatisticsCollectorService = \App::getInstance(ClaimCompleteAnalyticsCollectorService::class); | |
| if ($postData['totalChangePrice'] > 0) { | |
| $claimCompleteStatisticsCollectorService->collectAnalytics([ | |
| 'orderNo' => $postData['orderNo'], | |
| 'claimType' => ClaimType::EXCHANGE->value, | |
| 'claimAmount' => $postData['totalChangePrice'], | |
| ]); | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| return true; | |
| } | |
변경 전Wish.php
| use Repository\RegularDelivery\RegularGoods\RegularGoodsRepository; | |
| use Origin\Enum\RegularDelivery\RegularGoods\RegularGoodsAttribute; | |
| use Origin\Service\WebHook\CartWebHookService; | |
| class Wish | |
| { | |
| const ERROR_VIEW = 'ERROR_VIEW'; | |
| $result = $kafka->send($kafka::TOPIC_CART_ADD_STATISTICS, $kafka->makeData([$cartStatistics], 'cas'), $kafka::MODE_RESULT_CALLLBACK, true); | |
| \Logger::channel('kafka')->info('process sendMQ - return :', $result); | |
| $cartInfo = gd_policy('order.cart'); | |
| if($cartInfo['moveWishPageFl'] =='n') { | |
| //장바구니 저장 상품 삭제 | |
변경 후Wish.php
| use Repository\RegularDelivery\RegularGoods\RegularGoodsRepository; | |
| use Origin\Enum\RegularDelivery\RegularGoods\RegularGoodsAttribute; | |
| use Origin\Service\WebHook\CartWebHookService; | |
| use Origin\Service\Statistics\Analytics\Cart\CartAddHistoryAnalyticsCollectorService; | |
| use Origin\Repository\Wish\WishRepository; | |
| class Wish | |
| { | |
| const ERROR_VIEW = 'ERROR_VIEW'; | |
| $result = $kafka->send($kafka::TOPIC_CART_ADD_STATISTICS, $kafka->makeData([$cartStatistics], 'cas'), $kafka::MODE_RESULT_CALLLBACK, true); | |
| \Logger::channel('kafka')->info('process sendMQ - return :', $result); | |
| // 장바구니 추가 통계 수집 | |
| try { | |
| // 다중 insert 시 insert_id는 첫 sno만 반환 → insert된 cart 특정 불가, 원본 위시(es_wish) 조회 | |
| $wishRepository = \App::getInstance(WishRepository::class); | |
| $wishGoodsList = $wishRepository->findGoodsByWishSnosAndMemNo($sno, (int)Session::get('member.memNo')); | |
| if (!empty($wishGoodsList)) { | |
| $cartAddHistoryAnalyticsCollectorService = \App::getInstance(CartAddHistoryAnalyticsCollectorService::class); | |
| foreach ($wishGoodsList as $wishGoods) { | |
| $cartAddHistoryAnalyticsCollectorService->collectAnalytics($wishGoods); | |
| } | |
| } | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| $cartInfo = gd_policy('order.cart'); | |
| if($cartInfo['moveWishPageFl'] =='n') { | |
| //장바구니 저장 상품 삭제 | |
변경 전MemberPsController.php
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // 평생회원 이벤트 | |
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| $memNo = $memberVO->getMemNo(); | |
변경 후MemberPsController.php
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // 평생회원 이벤트 | |
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| $memNo = $memberVO->getMemNo(); | |
변경 전MemberPsController.php
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| // request가 ajax일 때 (카카오 싱크) | |
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('global')->error(__METHOD__ . ' analytics 수집 실패: ' . $e->getMessage(), [$e->getTraceAsString()]); | |
| } | |
| $memNo = $memberVO->getMemNo(); | |
변경 후MemberPsController.php
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| // request가 ajax일 때 (카카오 싱크) | |
| $memberStatisticsCollectorService = \App::getInstance(MemberJoinCompleteAnalyticsCollectorService::class); | |
| $memberStatisticsCollectorService->collectAnalytics($memberVO->toArray()); | |
| } catch (\Throwable $e) { | |
| \Logger::channel('analytics')->warning('analytics 수집 실패', ['exception' => $e, 'errorMessage' => $e->getMessage()]); | |
| } | |
| $memNo = $memberVO->getMemNo(); | |
변경 전excel_member_up.php
| <div class="notice-info"> | |
| 엑셀업로드 전 회원가입 시 발송 가능한 항목(회원가입, 마일리지 지급, 회원가입 축하 쿠폰)의 발송설정을 확인해주시기 바랍니다. <a href="/crm/auto_send.php" target="_blank" class="btn-link">SMS설정></a> <a href="/crm/mail_config_auto.php" target="_blank" class="btn-link">자동 메일 설정></a> | |
| </div> | |
| </td> | |
| </tr> | |
| </table> | |
변경 후excel_member_up.php
| <div class="notice-info"> | |
| 엑셀업로드 전 회원가입 시 발송 가능한 항목(회원가입, 마일리지 지급, 회원가입 축하 쿠폰)의 발송설정을 확인해주시기 바랍니다. <a href="/crm/auto_send.php" target="_blank" class="btn-link">SMS설정></a> <a href="/crm/mail_config_auto.php" target="_blank" class="btn-link">자동 메일 설정></a> | |
| </div> | |
| <div class="notice-info"> | |
| 마케팅 목적 개인정보 수집 및 이용 항목 업로드 시 반드시 고객으로부터 받은 별도의 개인정보 수집·이용 동의서를 보유하고 계셔야 하며, NHN COMMERCE는 수탁사로서 업로드되는 데이터에 대한 책임을 지지 않습니다. | |
| </div> | |
| </td> | |
| </tr> | |
| </table> | |
변경 전member_detail_search.php
| </td> | |
| </tr> | |
| <tr> | |
| <th>SMS수신동의</th> | |
| <td> | |
| <label class="radio-inline"> | |
| <input type="radio" name="smsFl" | |
변경 후member_detail_search.php
| </td> | |
| </tr> | |
| <tr> | |
| <th>마케팅 목적 개인정보 수집 및 이용 동의</th> | |
| <td colspan="3"> | |
| <label class="radio-inline"> | |
| <input type="radio" name="privateMarketingConsentOptionFl" | |
| value="" <?= gd_isset($checked['privateMarketingConsentOptionFl']['']); ?>/> | |
| 전체 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="privateMarketingConsentOptionFl" | |
| value="y" <?= gd_isset($checked['privateMarketingConsentOptionFl']['y']); ?>/> | |
| 동의 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="privateMarketingConsentOptionFl" | |
| value="n" <?= gd_isset($checked['privateMarketingConsentOptionFl']['n']); ?>/> | |
| 미동의 | |
| </label> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>모바일 메시지 수신동의</th> | |
| <td> | |
| <label class="radio-inline"> | |
| <input type="radio" name="smsFl" | |
변경 전member_joinitem.php
| </tr> | |
| <tr> | |
| <th>이메일</th> | |
| <td> | |
| <?php if ($mall['mallSno'] == 1) { ?> | |
| <label class="checkbox-inline" title="사용여부를 선택해주세요!"> | |
| <input type="checkbox" name="email[use]" value="y"/> | |
| <input type="hidden" name="email[require]" value="y"/> | |
| <?php } ?> | |
| </td> | |
| <td> | |
| <label class="checkbox-inline" for="maillingFl"> | |
| <input type="checkbox" id="maillingFl" name="maillingFl[use]" value="y"> | |
| 정보/이벤트 메일 수신 동의 사용 | |
| </label> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>휴대폰번호</th> | |
| <td <?= $mall['mallSno'] == 1 ? '' : 'colspan=2' ?>> | |
| <label class="checkbox-inline" title="사용여부를 선택해주세요!"> | |
| <input type="checkbox" name="cellPhone[use]" value="y"/> | |
| 사용 | |
| 필수 | |
| </label> | |
| </td> | |
| <?php if ($mall['mallSno'] == 1) { ?> | |
| <td> | |
| <label class="checkbox-inline" for="smsFl"> | |
| <input type="checkbox" id="smsFl" name="smsFl[use]" value="y"> | |
| 정보/이벤트 SMS 수신 동의 사용 | |
| </label> | |
| </td> | |
| <?php } ?> | |
| </tr> | |
| <?php if ($mall['mallSno'] == 1) { ?> | |
| <tr> | |
| } | |
| }); | |
| $(':checkbox[name="maillingFl[use]"], :checkbox[name="smsFl[use]"]', '#frmSetup').on('change', function (e) { | |
| var $target = $(e.target); | |
| if ($target.prop('checked') === false) { | |
| BootstrapDialog.confirm({ | |
| title: "정보/이벤트 메일(SMS)수신 동의 사용 체크 해제", | |
| message: "정보통신망법에 따라 수신동의한 회원에게만 정보/이벤트 소식을 전송할 수 있습니다. 수신동의 사용을 해제하시겠습니까?", | |
| btnCancelLabel: "취소", | |
| btnOkLabel: "해제", | |
| callback: function (result) { | |
| if (result) { | |
| $target.prop('checked', false); | |
| } else { | |
| $target.prop('checked', true); | |
| } | |
| } | |
| }); | |
| } | |
| }); | |
| $('.expiration_detail').on('click', function () { | |
| var msg = "휴면회원 정책에서 휴면회원 ‘사용함’으로 설정할 경우, 일정 기간 동안 쇼핑몰을 이용하지 않는 회원은 휴면회원으로 전환되어 쇼핑몰의 이용이 제한되고, 쇼핑몰 운영자는 회원에게 정보/이벤트성 안내를 할 수 없습니다."+'<br>'+"- 회원가입 항목에서 개인 정보 유효기간 미사용 시 1년간 쇼핑몰을 이용하지 않는 회원들을 "+'<br>'+" 휴면회원으로 일괄 전환합니다."+'<br>'+"- 개인 정보 유효기간 사용 시 회원에게 ‘휴면회원 방지기간’ 정보를 수집할 수 있으며, 각 회원이 "+'<br>'+" “1년(기본값)/3년/5년/탈퇴 시” 중 선택한 기간 동안 쇼핑몰을 이용하지 않는 경우 해당 회원의"+'<br>'+" 정보를 휴면회원으로 전환합니다."+'<br><div><img src="../admin/gd_share/img/expirationFl_img.png" style="width:80%; height:100%; margin-top:20px; margin-left:50px;"></div>' + | |
| '<br>'+"휴면회원 정책에서 휴면회원 ‘사용 안함’으로 설정할 경우, 각 회원별로 개인정보 유효기간이 만료되더라도 휴면회원으로 전환되지 않으며 계속 쇼핑몰을 이용할 수 있습니다."+'<br>'; | |
변경 후member_joinitem.php
| </tr> | |
| <tr> | |
| <th>이메일</th> | |
| <td colspan="2"> | |
| <?php if ($mall['mallSno'] == 1) { ?> | |
| <label class="checkbox-inline" title="사용여부를 선택해주세요!"> | |
| <input type="checkbox" name="email[use]" value="y"/> | |
| <input type="hidden" name="email[require]" value="y"/> | |
| <?php } ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>휴대폰번호</th> | |
| <td colspan="2"> | |
| <label class="checkbox-inline" title="사용여부를 선택해주세요!"> | |
| <input type="checkbox" name="cellPhone[use]" value="y"/> | |
| 사용 | |
| 필수 | |
| </label> | |
| </td> | |
| </tr> | |
| <?php if ($mall['mallSno'] == 1) { ?> | |
| <tr> | |
| } | |
| }); | |
| $('.expiration_detail').on('click', function () { | |
| var msg = "휴면회원 정책에서 휴면회원 ‘사용함’으로 설정할 경우, 일정 기간 동안 쇼핑몰을 이용하지 않는 회원은 휴면회원으로 전환되어 쇼핑몰의 이용이 제한되고, 쇼핑몰 운영자는 회원에게 정보/이벤트성 안내를 할 수 없습니다."+'<br>'+"- 회원가입 항목에서 개인 정보 유효기간 미사용 시 1년간 쇼핑몰을 이용하지 않는 회원들을 "+'<br>'+" 휴면회원으로 일괄 전환합니다."+'<br>'+"- 개인 정보 유효기간 사용 시 회원에게 ‘휴면회원 방지기간’ 정보를 수집할 수 있으며, 각 회원이 "+'<br>'+" “1년(기본값)/3년/5년/탈퇴 시” 중 선택한 기간 동안 쇼핑몰을 이용하지 않는 경우 해당 회원의"+'<br>'+" 정보를 휴면회원으로 전환합니다."+'<br><div><img src="../admin/gd_share/img/expirationFl_img.png" style="width:80%; height:100%; margin-top:20px; margin-left:50px;"></div>' + | |
| '<br>'+"휴면회원 정책에서 휴면회원 ‘사용 안함’으로 설정할 경우, 각 회원별로 개인정보 유효기간이 만료되더라도 휴면회원으로 전환되지 않으며 계속 쇼핑몰을 이용할 수 있습니다."+'<br>'; | |
변경 전member_modify.php
| <form id="frm" action="../member/member_ps.php" method="post" enctype="multipart/form-data"> | |
| <div class="page-header js-affix"> | |
| <h3>회원 수정 </h3> | |
| <input type="button" value="저장" class="btn btn-red btn-register"> | |
| </form> | |
| <?php | |
| // 모바일앱 정보 | |
| if ($hasDeviceInfo) { | |
| include('_member_view_app_device.php'); | |
| } | |
| ?> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script type="text/javascript"> | |
| member2.init($('#frm')); | |
| member2.set_my_page(true); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
변경 후member_modify.php
| <link rel="stylesheet" href="<?= PATH_ADMIN_GD_SHARE ?>ncds/css/member/member-view.css"> | |
| <form id="frm" action="../member/member_ps.php" method="post" enctype="multipart/form-data" class="ncua-content"> | |
| <div class="page-header js-affix"> | |
| <h3>회원 수정 </h3> | |
| <input type="button" value="저장" class="btn btn-red btn-register"> | |
| </form> | |
| <?php | |
| // 모바일앱 정보 | |
| if (!empty($hasDeviceInfo)) { | |
| include('_member_view_app_device.php'); | |
| } | |
| ?> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script defer src="<?=gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/charcount.js')?>"></script> | |
| <script type="text/javascript"> | |
| member2.init($('#frm')); | |
| member2.set_my_page(true); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| const memberPwManager = createCharCountManager({ | |
| targetClasses: ['js-member-pw'], | |
| }); | |
| memberPwManager.init(); | |
| const reMemberPwManager = createCharCountManager({ | |
| targetClasses: ['js-re-member-pw'], | |
| }); | |
| reMemberPwManager.init(); | |
| }); | |
| </script> | |
변경 전member_register.php
| <form id="frm" action="../member/member_ps.php" method="post" enctype="multipart/form-data"> | |
| <div class="page-header js-affix"> | |
| <h3>회원 등록 </h3> | |
| <div class="btn-group"> | |
| <input type="button" value="목록" class="btn btn-white btn-icon-list" onclick="goList('./member_list.php');"/> | |
| <input type="button" value="저장" class="btn btn-red btn-register"> | |
| </div> | |
| </div> | |
| </form> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script type="text/javascript"> | |
| member2.init($('#frm')); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
변경 후member_register.php
| <link rel="stylesheet" href="<?= PATH_ADMIN_GD_SHARE ?>ncds/css/member/member-view.css"> | |
| <form id="frm" class="ncua-content" action="../member/member_ps.php" method="post" enctype="multipart/form-data"> | |
| <div class="page-header js-affix"> | |
| <h3 class="ncua-help-manual">회원 등록</h3> | |
| <div class="btn-group"> | |
| <input type="button" value="목록" class="btn btn-white" onclick="goList('./member_list.php');"/> | |
| <input type="button" value="저장" class="btn btn-red btn-register"> | |
| </div> | |
| </div> | |
| </form> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script defer src="<?=gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/charcount.js')?>"></script> | |
| <script type="text/javascript"> | |
| member2.init($('#frm')); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| const memberPwManager = createCharCountManager({ | |
| targetClasses: ['js-member-pw'], | |
| }); | |
| memberPwManager.init(); | |
| const reMemberPwManager = createCharCountManager({ | |
| targetClasses: ['js-re-member-pw'], | |
| }); | |
| reMemberPwManager.init(); | |
| }); | |
| </script> | |
| <script type="text/javascript"> | |
| const code = '260713001'; | |
| if (window.GodoCosGuide) { | |
| window.GodoCosGuide.init({ | |
| apiUrl: <?= json_encode($cosGuideApiUrl) ?>, | |
| guideCode: code, | |
| }); | |
| } | |
| </script> | |
변경 전_member_view_app_device.php
| <div class="table-title"> | |
| 모바일앱 정보 | |
| </div> | |
| <div class="form-inline"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col/> | |
| </colgroup> | |
| <tr> | |
| <th>혜택 정보</th> | |
| <td> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-md"/> | |
| <col class="width-md"/> | |
| <col class="width-md"/> | |
| <col/> | |
| </colgroup> | |
| <tr> | |
| <th>앱 설치 혜택</th> | |
| <td><?=$installBenefitReceived;?></td> | |
| <th>최초 로그인 일시</th> | |
| <td> | |
| <?=$firstLoginDateTime;?><br> | |
| <p class="notice-danger notice-info">앱을 접속한 최초 일시입니다.</p> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>앱 알림 혜택</th> | |
| <td><?=$pushBenefitReceived;?></td> | |
| <th>혜택 지급 일시</th> | |
| <td> | |
| <?=$pushBenefitReceivedDateTime?><br> | |
| <p class="notice-danger notice-info">앱에서 알림 혜택이 지급된 일시입니다.</p> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>앱 주문 혜택</th> | |
| <td><?=$firstOrderBenefitReceived;?></td> | |
| <th>최초 주문 일시</th> | |
| <td> | |
| <?=$firstOrderDateTime;?><br> | |
| <p class="notice-danger notice-info">앱에서 결제완료한 최초 일시입니다.</p> | |
| </td> | |
| </tr> | |
| </table> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>접속 정보</th> | |
| <td> | |
| <table class="table table-rows"> | |
| <colgroup> | |
| <col class="width-xs"/> | |
| <col class="width-md"/> | |
| <col class="width-sm"/> | |
| <col class="width-sm"/> | |
| <col class="width-md"/> | |
| <col/> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>운영체제</th> | |
| <th>모바일 기종</th> | |
| <th>최근 로그인 일시</th> | |
| <th>정보성 알림 수신 동의</th> | |
| <th>광고성 알림 수신 동의</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td class="center"><?=$deviceInfos['platform'];?></td> | |
| <td class="center"><?=$deviceInfos['deviceModel'];?></td> | |
| <td class="center"><?=$deviceInfos['latestLoginDateTime'];?></td> | |
| <td class="center"><?=$deviceInfos['isNotificationAgreed'];?></td> | |
| <td class="center"><?=$deviceInfos['isAdNotificationAgreed'];?></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <p class="notice-danger notice-info">최근 90일내 접속한 디바이스가 표시됩니다.</p> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
변경 후_member_view_app_device.php
| <section class="ncua-block-container ncua-content ncua-member-mobile-device"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <span class="ncua-block-header__title">모바일앱 정보</span> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 120px;"/> | |
| <col/> | |
| </colgroup> | |
| <tr> | |
| <th><div>혜택 정보</div></th> | |
| <td class="ncua-member-mobile-benefit-info"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 120px;"/> | |
| <col /> | |
| <col style="width: 120px;"/> | |
| <col/> | |
| </colgroup> | |
| <tr> | |
| <th><div>앱 설치 혜택</div></th> | |
| <td><div><?=$installBenefitReceived;?></div></td> | |
| <th><div>최초 로그인 일시</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start"> | |
| <?=$firstLoginDateTime;?><br> | |
| <p class="notice-danger notice-info">앱을 접속한 최초 일시입니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th><div>앱 알림 혜택</div></th> | |
| <td><div><?=$pushBenefitReceived;?></div></td> | |
| <th><div>혜택 지급 일시</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start"> | |
| <?=$pushBenefitReceivedDateTime?><br> | |
| <p class="notice-danger notice-info">앱에서 알림 혜택이 지급된 일시입니다.</p></div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th><div>앱 주문 혜택</div></th> | |
| <td><div><?=$firstOrderBenefitReceived;?></div></td> | |
| <th><div>최초 주문 일시</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start"> | |
| <?=$firstOrderDateTime;?><br> | |
| <p class="notice-danger notice-info">앱에서 결제완료한 최초 일시입니다.</p></div> | |
| </td> | |
| </tr> | |
| </table> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th><div>접속 정보</div></th> | |
| <td class="ncua-member-access-info"> | |
| <div> | |
| <div class="ncua-table ncua-table--horizontal"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th><div class="ncua-align-center">운영체제</div></th> | |
| <th><div class="ncua-align-center">모바일 기종</div></th> | |
| <th><div class="ncua-align-center">최근 로그인 일시</div></th> | |
| <th><div class="ncua-align-center">정보성 알림 수신 동의</div></th> | |
| <th><div class="ncua-align-center">광고성 알림 수신 동의</div></th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td><div class="ncua-align-center"><?=$deviceInfos['platform'];?></div></td> | |
| <td><div class="ncua-align-center"><?=$deviceInfos['deviceModel'];?></div></td> | |
| <td><div class="ncua-align-center"><?=$deviceInfos['latestLoginDateTime'];?></div></td> | |
| <td><div class="ncua-align-center"><?=$deviceInfos['isNotificationAgreed'];?></div></td> | |
| <td><div class="ncua-align-center"><?=$deviceInfos['isAdNotificationAgreed'];?></div></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
| <p class="ncua-notice-info">최근 90일내 접속한 디바이스가 표시됩니다.</p> | |
| </div> | |
| </section> | |
변경 전_member_view_business.php
| } ?>">(<?php echo $data['comZipcode']; ?>)</span> | |
| <input type="button" | |
| onclick="postcode_search('comZonecode', 'comAddress', 'comZipcode');" | |
| value="우편번호" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray"/> | |
| <!-- addr2 --> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr2"> | |
| <div class="ncua-input__content"> | |
| <div class="table-title div-business gd-help-manual"> | |
| 사업자정보 | |
| </div> | |
| <div class="input_wrap form-inline div-business"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col class="<?=(!empty($widthClass)) ? $widthClass : 'width-3xl'?>"/> | |
| <col class="width-sm"/> | |
| <col class="<?=(!empty($widthClass)) ? $widthClass : ''?>"/> | |
| </colgroup> | |
| <tr> | |
| <th>상호</th> | |
| <td> | |
| <span title="회사명를 입력해주세요!"> | |
| <input type="text" name="company" class="form-control" value="<?= $data['company']; ?>" maxlength="50" data-pattern="gdMemberNmGlobal"/> | |
| </span> | |
| <span id="companyMsg" class="input_error_msg"></span> | |
| </td> | |
| <th>사업자번호</th> | |
| <td> | |
| <span title="사업자번호를 입력해주세요!"> | |
| <input type="text" name="busiNo[]" size="3" maxlength="3" class="form-control js-number" | |
| value="<?= $data['busiNo'][0]; ?>"/> | |
| - | |
| <input type="text" name="busiNo[]" size="2" maxlength="2" class="form-control js-number" | |
| value="<?= $data['busiNo'][1]; ?>"/> | |
| - | |
| <input type="text" name="busiNo[]" size="5" maxlength="5" class="form-control js-number" | |
| value="<?= $data['busiNo'][2]; ?>"/> | |
| <input type="hidden" id="busiNo" name="fullBusiNo" class="error" value="<?= gd_implode('', $data['busiNo']); ?>" data-overlap-businofl="<?= $joinField['busiNo']['overlapBusiNoFl']; ?>" data-charlen="<?= $joinField['busiNo']['charlen']; ?>" data-oldbusino="<?= gd_implode('', $data['busiNo']); ?>"/> | |
| <?php if ($joinField['busiNo']['overlapBusiNoFl'] == 'y') { ?> | |
| <button type="button" id="overlap_busiNo" class="btn btn-gray btn-sm">중복확인</button> | |
| <?php } ?> | |
| <button type="button" id="find_busiNo" class="btn btn-gray btn-sm">사업자번호 조회</button> | |
| </span> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>대표자명</th> | |
| <td class="input_area" colspan="3"> | |
| <span title="대표자를 입력해주세요!"> | |
| <input type="text" name="ceo" class="form-control" value="<?= $data['ceo']; ?>" data-pattern="gdEngKor" maxlength="20"/> | |
| </span> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>업태</th> | |
| <td> | |
| <span title="업태를 입력해주세요!"> | |
| <input type="text" name="service" class="form-control" value="<?= $data['service']; ?>" data-pattern="gdEngKor" maxlength="30"/> | |
| </span> | |
| </td> | |
| <th>종목</th> | |
| <td> | |
| <span title="종목을 입력해주세요!"> | |
| <input type="text" name="item" class="form-control" value="<?= $data['item']; ?>" data-pattern="gdEngKor" maxlength="30"/> | |
| </span> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>사업장 주소</th> | |
| <td class="input_area" colspan="3"> | |
| <div class="form-inline mgb5"> | |
| <span title="우편번호를 입력해주세요!"> | |
| <input type="text" size="7" maxlength="5" name="comZonecode" class="form-control" | |
| value="<?= $data['comZonecode'] ?>"/> | |
| <input type="hidden" name="comZipcode" value="<?= $data['comZipcode'] ?>"/> | |
| <span id="comZipcodeText" class="number <?php if (strlen($data['comZipcode']) != 7) { | |
| echo 'display-none'; | |
| } ?>">(<?php echo $data['comZipcode']; ?>) | |
| </span> | |
| </span> | |
| <input type="button" | |
| onclick="postcode_search('comZonecode', 'comAddress', 'comZipcode');" | |
| value="우편번호찾기" class="btn btn-sm btn-gray"/> | |
| </div> | |
| <div> | |
| <span title="주소를 입력해주세요!"> | |
| <input type="text" name="comAddress" class="form-control width-2xl" | |
| value="<?= $data['comAddress']; ?>"/> | |
| </span> | |
| <span title="상세주소를 입력해주세요!"> | |
| <input type="text" name="comAddressSub" | |
| class="form-control width-2xl" | |
| value="<?= $data['comAddressSub']; ?>"/> | |
| </span> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>사업자등록증</th> | |
| <td class="input_area" colspan="3"> | |
| <?php if (!empty($certification)): ?> | |
| <a href="#" class="js-certification-download" data-url="../member/company_certification.php?mode=download&sno=<?= $certification['sno'] ?>"> | |
| <?= $certification['imageFileNm'] ?> | |
| </a> | |
| <br> | |
| <?php endif; ?> | |
| <div class="form-inline"> | |
| <input type="file" id="companyCertification" name="companyCertification" class="form-control js-cert-file" accept="image/*, application/pdf" data-max-size="<?= $certificationMaxFileSize ?>"/> | |
| <?php if ($mode === 'register'): // 등록 시에만 첨부 취소 버튼 노출 (수정 시 미노출) ?> | |
| <button type="button" class="btn btn-white btn-sm js-cert-file-clear" style="display:none;">- 삭제</button> | |
| <?php endif; ?> | |
| </div> | |
| <div class="notice-info mgt10"> | |
| 파일 업로드 최대 사이즈는 <?= $certificationMaxFileSize ?>MB 입니다.<br> | |
| </div> | |
| <?php if (!empty($certification)): ?> | |
| <span> | |
| <input type="checkbox" name="certificationDeleteSno" class="js-certification-checkbox" value="<?= $certification['sno'] ?>" /> | |
| 업로드된 파일 삭제 .. <?= $certification['imageFileNm'] ?> | |
| <br> | |
| </span> | |
| <?php endif; ?> | |
| </td> | |
| </tr> | |
| <?php | |
| for ($i = 0; $i < $certificationAdditionalFileCount ; $i++) { | |
| $additional = $additionalCertification["comAddiCert$i"] ?? null; | |
| if($additional && $additional['use'] === 'y') { ?> | |
| <tr> | |
| <th><?= $additional['name'] ?></th> | |
| <td class="input_area" colspan="3"> | |
| <?php if (!empty($additional['file'])): ?> | |
| <a href="#" class="js-certification-download" data-url="../member/company_certification.php?mode=download&sno=<?= $additional['file']['sno'] ?>"> | |
| <?= $additional['file']['imageFileNm'] ?> | |
| </a> | |
| <br> | |
| <?php endif; ?> | |
| <div class="form-inline"> | |
| <input type="file" id="comAddiCert[<?= $i ?>][file]" name="comAddiCert[<?= $i ?>][file]" class="form-control js-cert-file" accept="image/*, application/pdf" data-max-size="<?= $additional['certificationFileSize'] ?>"/> | |
| <?php if ($mode === 'register'): // 등록 시에만 첨부 취소 버튼 노출 (수정 시 미노출) ?> | |
| <button type="button" class="btn btn-white btn-sm js-cert-file-clear" style="display:none;">- 삭제</button> | |
| <?php endif; ?> | |
| </div> | |
| <div class="notice-info mgt10"> | |
| 파일 업로드 최대 사이즈는 <?= $additional['certificationFileSize'] ?>MB 입니다.<br> | |
| </div> | |
| <?php if (!empty($additional['file'])): ?> | |
| <span> | |
| <input type="checkbox" name="comAddiCert[<?= $i ?>][DeleteSno]" class="js-certification-checkbox" value="<?= $additional['file']['sno'] ?>" /> | |
| 업로드된 파일 삭제 .. <?= $additional['file']['imageFileNm'] ?> | |
| <br> | |
| </span> | |
| <?php endif; ?> | |
| </td> | |
| </tr> | |
| <?php | |
| } | |
| } ?> | |
| </table> | |
| </div> | |
| <iframe id="downloadFrame" style="display:none;"></iframe> | |
| <script> | |
| $(document).on('click', '.js-certification-download', function(e) { | |
| e.preventDefault(); | |
| var url = $(this).data('url'); | |
| $('#downloadFrame').attr('src', url); | |
| }); | |
| $(document).on('change', '.js-certification-checkbox', function(e) { | |
| var checkbox = this; | |
| if (checkbox.checked) { | |
| // 추가서류(comAddiCert[N][DeleteSno])와 사업자등록증(certificationDeleteSno) 문구 구분 | |
| var message = checkbox.name.indexOf('comAddiCert') === 0 | |
| ? '등록된 첨부파일을 삭제하시겠습니까? 회원정보 최종 저장 시 삭제되며, 복구가 불가능 합니다.' | |
| : '등록된 사업자등록증을 삭제하시겠습니까? 회원정보 최종 저장 시 삭제되며, 복구가 불가합니다.'; | |
| dialog_confirm(message, function(result) { | |
| if (!result) { | |
| checkbox.checked = false; | |
| } | |
| }, '경고'); | |
| } | |
| }); | |
| // 선택 파일 비우기: bootstrap-filestyle 위젯이 적용된 경우 표시 텍스트박스까지 함께 비운다 | |
| function clearCertFile($input) { | |
| if ($input.data('filestyle')) { | |
| $input.filestyle('clear'); | |
| } else { | |
| $input.val(''); | |
| } | |
| } | |
| // 찾아보기로 파일 선택 시 확장자·용량 검사 후 '- 삭제' 버튼 노출, 클릭 시 선택 취소(첨부 제거) | |
| $(document).on('change', '.js-cert-file', function () { | |
| const file = this.files[0]; | |
| if (file) { | |
| const allowedExt = ['pdf', 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']; | |
| const ext = file.name.split('.').pop().toLowerCase(); | |
| if (!allowedExt.includes(ext)) { | |
| clearCertFile($(this)); | |
| dialog_alert('등록이 불가한 파일 형식입니다. 이미지(jpg, jpeg, png, gif, bmp, webp, svg) 및 pdf 파일만 업로드 가능합니다.'); | |
| } else { | |
| const fileMaxSize = parseFloat($(this).data('max-size')) || 2; // MB | |
| const fileSizeMB = file.size / (1024 * 1024); | |
| if (fileSizeMB > fileMaxSize) { | |
| clearCertFile($(this)); | |
| dialog_alert('파일은 최대 ' + fileMaxSize.toString() + 'MB 이하로만 등록 가능합니다.'); | |
| } | |
| } | |
| } | |
| $(this).closest('.form-inline').find('.js-cert-file-clear').toggle(this.files.length > 0); | |
| }); | |
| $(document).on('click', '.js-cert-file-clear', function () { | |
| clearCertFile($(this).closest('.form-inline').find('.js-cert-file')); | |
| $(this).hide(); | |
| }); | |
| </script> | |
변경 후_member_view_business.php
| } ?>">(<?php echo $data['comZipcode']; ?>)</span> | |
| <input type="button" | |
| onclick="postcode_search('comZonecode', 'comAddress', 'comZipcode');" | |
| value="주소찾기" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray"/> | |
| <!-- addr2 --> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr2"> | |
| <div class="ncua-input__content"> | |
| <section class="ncua-block-container div-business ncua-member-business"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <div class="ncua-block-header__title-area"> | |
| <span class="ncua-block-header__title">사업자정보</span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 240px;"/> | |
| <col /> | |
| </colgroup> | |
| <!-- 상호 --> | |
| <tr> | |
| <th><div>상호</div></th> | |
| <td><div class="ncua-gap-4"> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="company" value="<?= $data['company']; ?>" maxlength="50" data-pattern="gdMemberNmGlobal" title="회사명를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| <span id="companyMsg" class="input_error_msg"></span> | |
| </div></td> | |
| </tr> | |
| <!-- 사업자번호 --> | |
| <tr> | |
| <th><div>사업자번호</div></th> | |
| <td><div class="ncua-flex ncua-align-items-center ncua-gap-4"> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-80"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="busiNo[]" maxlength="3" class="js-number" value="<?= $data['busiNo'][0]; ?>"/> | |
| </div> | |
| </div> | |
| </div> | |
| - | |
| <div class="ncua-input ncua-input--xs ncua-input-width-80"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="busiNo[]" maxlength="2" class="js-number" value="<?= $data['busiNo'][1]; ?>"/> | |
| </div> | |
| </div> | |
| </div> | |
| - | |
| <div class="ncua-input ncua-input--xs ncua-input-width-100"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="busiNo[]" maxlength="5" class="js-number" value="<?= $data['busiNo'][2]; ?>"/> | |
| </div> | |
| </div> | |
| </div> | |
| <input type="hidden" id="busiNo" name="fullBusiNo" class="error" value="<?= gd_implode('', $data['busiNo']); ?>" data-overlap-businofl="<?= $joinField['busiNo']['overlapBusiNoFl']; ?>" data-charlen="<?= $joinField['busiNo']['charlen']; ?>" data-oldbusino="<?= gd_implode('', $data['busiNo']); ?>"/> | |
| <?php if ($joinField['busiNo']['overlapBusiNoFl'] == 'y') { ?> | |
| <button type="button" id="overlap_busiNo" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">중복확인</button> | |
| <?php } ?> | |
| <button type="button" id="find_busiNo" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">사업자번호 조회</button> | |
| </div></td> | |
| </tr> | |
| <!-- 대표자명 --> | |
| <tr> | |
| <th><div>대표자명</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="ceo" value="<?= $data['ceo']; ?>" data-pattern="gdEngKor" maxlength="20" title="대표자를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| <!-- 업태 --> | |
| <tr> | |
| <th><div>업태</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="service" value="<?= $data['service']; ?>" data-pattern="gdEngKor" maxlength="30" title="업태를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| <!-- 종목 --> | |
| <tr> | |
| <th><div>종목</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="item" value="<?= $data['item']; ?>" data-pattern="gdEngKor" maxlength="30" title="종목을 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| <!-- 사업장 주소 --> | |
| <tr> | |
| <th><div>사업장 주소</div></th> | |
| <td><div> | |
| <div class="ncua-member-addr"> | |
| <!-- addr1 --> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr1"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" maxlength="5" name="comZonecode" value="<?= $data['comZonecode'] ?>" title="우편번호를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| <input type="hidden" name="comZipcode" value="<?= $data['comZipcode'] ?>"/> | |
| <span id="comZipcodeText" class="number <?php if (strlen($data['comZipcode']) != 7) { | |
| echo 'display-none'; | |
| } ?>">(<?php echo $data['comZipcode']; ?>)</span> | |
| <input type="button" | |
| onclick="postcode_search('comZonecode', 'comAddress', 'comZipcode');" | |
| value="우편번호" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray"/> | |
| <!-- addr2 --> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr2"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="comAddress" value="<?= $data['comAddress']; ?>" title="주소를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- addr3 --> | |
| <div class="ncua-input ncua-input--xs ncua-member-addr2"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="comAddressSub" value="<?= $data['comAddressSub']; ?>" title="상세주소를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| <!-- 사업자등록증 --> | |
| <tr> | |
| <th><div>사업자등록증</div></th> | |
| <td><div> | |
| <?php if (!empty($certification)): ?> | |
| <a href="#" class="js-certification-download" data-url="../member/company_certification.php?mode=download&sno=<?= $certification['sno'] ?>"> | |
| <?= $certification['imageFileNm'] ?> | |
| </a> | |
| <?php endif; ?> | |
| <div class="member-cert-upload"> | |
| <div id="companyCertificationFileInput"></div> | |
| <input type="file" id="companyCertification" name="companyCertification" accept="image/*, application/pdf" class="no-filestyle" style="display:none"/> | |
| <div id="companyCertificationTags" class="member-cert-files"></div> | |
| </div> | |
| <?php if (!empty($certification)): ?> | |
| <label class="ncua-checkbox-field ncua-checkbox-field--xs has-text"> | |
| <span class="ncua-checkbox-input ncua-checkbox-input--xs ncua-checkbox-field__input"> | |
| <input type="checkbox" name="certificationDeleteSno" class="js-certification-checkbox" value="<?= $certification['sno'] ?>" /> | |
| </span> | |
| <span><span class="ncua-checkbox-field__text">Delete Uploaded File .. <?= $certification['imageFileNm'] ?></span></span> | |
| </label> | |
| <?php endif; ?> | |
| </div></td> | |
| </tr> | |
| <?php | |
| // 추가서류: 사업자등록증과 동일하게 ncua.FileInput 위젯 사용 (행마다 별도 인스턴스) | |
| $addiCertInits = []; | |
| for ($i = 0; $i < $certificationAdditionalFileCount ; $i++) { | |
| $additional = $additionalCertification["comAddiCert$i"] ?? null; | |
| if($additional && $additional['use'] === 'y') { | |
| $addiCertInits[] = ['i' => $i, 'maxSize' => (float)($additional['certificationFileSize'] ?? 2)]; | |
| ?> | |
| <tr> | |
| <th><div><?= $additional['name'] ?></div></th> | |
| <td><div> | |
| <?php if (!empty($additional['file'])): ?> | |
| <a href="#" class="js-certification-download" data-url="../member/company_certification.php?mode=download&sno=<?= $additional['file']['sno'] ?>"> | |
| <?= $additional['file']['imageFileNm'] ?> | |
| </a> | |
| <?php endif; ?> | |
| <div class="member-cert-upload"> | |
| <div id="comAddiCertFileInput_<?= $i ?>"></div> | |
| <input type="file" id="comAddiCertCarrier_<?= $i ?>" name="comAddiCert[<?= $i ?>][file]" accept="image/*, application/pdf" class="no-filestyle" style="display:none"/> | |
| <div id="comAddiCertTags_<?= $i ?>" class="member-cert-files"></div> | |
| </div> | |
| <?php if (!empty($additional['file'])): ?> | |
| <label class="ncua-checkbox-field ncua-checkbox-field--xs has-text"> | |
| <span class="ncua-checkbox-input ncua-checkbox-input--xs ncua-checkbox-field__input"> | |
| <input type="checkbox" name="comAddiCert[<?= $i ?>][DeleteSno]" class="js-certification-checkbox" value="<?= $additional['file']['sno'] ?>" /> | |
| </span> | |
| <span><span class="ncua-checkbox-field__text">업로드된 파일 삭제 .. <?= $additional['file']['imageFileNm'] ?></span></span> | |
| </label> | |
| <?php endif; ?> | |
| </div></td> | |
| </tr> | |
| <?php | |
| } | |
| } ?> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <iframe id="downloadFrame" style="display:none;"></iframe> | |
| <script> | |
| $(document).on('click', '.js-certification-download', function(e) { | |
| e.preventDefault(); | |
| var url = $(this).data('url'); | |
| $('#downloadFrame').attr('src', url); | |
| }); | |
| $(document).on('change', '.js-certification-checkbox', function(e) { | |
| var checkbox = this; | |
| if (checkbox.checked) { | |
| // 추가서류(comAddiCert[N][DeleteSno])와 사업자등록증(certificationDeleteSno) 문구 구분 | |
| var message = checkbox.name.indexOf('comAddiCert') === 0 | |
| ? '등록된 첨부파일을 삭제하시겠습니까? 회원정보 최종 저장 시 삭제되며, 복구가 불가능 합니다.' | |
| : '등록된 사업자등록증을 삭제하시겠습니까? 회원정보 최종 저장 시 삭제되며, 복구가 불가합니다.'; | |
| dialog_confirm(message, function(result) { | |
| if (!result) { | |
| checkbox.checked = false; | |
| } | |
| }, '경고'); | |
| } | |
| }); | |
| </script> | |
| <script> | |
| // 사업자등록증/추가서류 공통: ncua.FileInput 위젯 초기화 (파일을 폼 제출용 carrier input에 주입) | |
| function initCertFileInput(opts) { | |
| const tagContainer = document.getElementById(opts.tagsId); | |
| const carrier = document.getElementById(opts.carrierId); | |
| if (!tagContainer || !carrier) { | |
| return; | |
| } | |
| let currentTag = null; | |
| // 선택 파일을 폼 제출용 file input에 주입 (multipart 전송) | |
| const setCarrierFile = function (file) { | |
| const dt = new DataTransfer(); | |
| if (file) { | |
| dt.items.add(file); | |
| } | |
| carrier.files = dt.files; | |
| }; | |
| new ncua.FileInput({ | |
| container: opts.containerId, | |
| buttonLabel: '파일 찾기', | |
| multiple: false, | |
| size: 'xs', | |
| accept: '.pdf,.jpg,.jpeg,.png,.gif,.bmp,.webp,.svg', | |
| maxFileSize: opts.maxSizeMB * 1024 * 1024, | |
| hintItems: ['파일 업로드 최대 사이즈는 ' + opts.maxSizeMB + 'MB 입니다.'], | |
| // 파일 선택 시: (1) carrier input에 주입해 제출 (2) 회색 영역에 파일명 태그 + 썸네일 표시 (단일 파일) | |
| onChange: function (newFiles) { | |
| tagContainer.innerHTML = ''; | |
| currentTag = null; | |
| const file = (newFiles || [])[0]; | |
| setCarrierFile(file); | |
| if (!file) { | |
| return; | |
| } | |
| // 파일명 태그 + 삭제 버튼 | |
| currentTag = new ncua.Tag({ | |
| text: file.name, | |
| size: 'sm', | |
| close: true, | |
| onButtonClick: function () { | |
| tagContainer.innerHTML = ''; | |
| currentTag = null; | |
| setCarrierFile(null); | |
| }, | |
| }); | |
| tagContainer.appendChild(currentTag.getElement()); | |
| // 이미지 파일이면 썸네일 미리보기 | |
| if (file.type && file.type.indexOf('image/') === 0) { | |
| const reader = new FileReader(); | |
| reader.onload = function (ev) { | |
| const img = document.createElement('img'); | |
| img.className = 'member-cert-files__thumb'; | |
| img.src = ev.target.result; | |
| img.alt = file.name; | |
| tagContainer.appendChild(img); | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| }, | |
| onFail: function () { | |
| dialog_alert('이미지(jpg, jpeg, png, gif, bmp, webp, svg) 및 pdf 파일만, 최대 ' + opts.maxSizeMB + 'MB 이하로 등록 가능합니다.'); | |
| }, | |
| }); | |
| } | |
| document.addEventListener('DOMContentLoaded', function () { | |
| const certMaxSizeMB = (typeof certificationMaxFileSize !== 'undefined' ? certificationMaxFileSize : 2); | |
| // 사업자등록증 | |
| initCertFileInput({ | |
| containerId: 'companyCertificationFileInput', | |
| carrierId: 'companyCertification', | |
| tagsId: 'companyCertificationTags', | |
| maxSizeMB: certMaxSizeMB, | |
| }); | |
| // 추가서류 (행마다 별도 인스턴스) | |
| var addiCertInits = <?= json_encode($addiCertInits) ?>; | |
| addiCertInits.forEach(function (cfg) { | |
| initCertFileInput({ | |
| containerId: 'comAddiCertFileInput_' + cfg.i, | |
| carrierId: 'comAddiCertCarrier_' + cfg.i, | |
| tagsId: 'comAddiCertTags_' + cfg.i, | |
| maxSizeMB: cfg.maxSize, | |
| }); | |
| }); | |
| }); | |
| </script> | |
변경 전_member_view_history.php
| <form id="frmHistory" method="get"> | |
| <input type="hidden" name="pageNum"/> | |
| <div class="table-title"> | |
| 회원정보 수정이력 | |
| </div> | |
| <div class="table-header"> | |
| <div class="pull-right"> | |
| <div class="form-inline"> | |
| <?= gd_select_box_by_page_view_count(Request::get()->get('pageNum', 10), null, null, ''); ?> | |
| </div> | |
| </div> | |
| </div> | |
| <table class="table table-rows"> | |
| <colgroup> | |
| <col class="width-xs"/> | |
| <col class="width-md"/> | |
| <col class="width-sm"/> | |
| <col class="width-sm"/> | |
| <col class="width-md"/> | |
| <col/> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>번호</th> | |
| <th>변경일자</th> | |
| <th>처리자</th> | |
| <th>IP주소</th> | |
| <th>변경항목</th> | |
| <th>변경내용</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| </tbody> | |
| </table> | |
| <div class="center" id="div-pagination"></div> | |
| </form> | |
| <script type="text/template" id="history-row-template2"> | |
| <% _.each(data, function(item){ %> | |
| <% if(item.updateColumn !== '최종구매일') { %> | |
| <tr class="center"> | |
| <td class="font-num"><%- item.idx %></td> | |
| <td class="font-date"><%- item.regDt %></td> | |
| <td><%- item.processor %><%- item.deleteText %></td> | |
| <td><%- item.processorIp %></td> | |
| <td><%- item.updateColumn %></td> | |
| <% if(item.updateColumn === '비밀번호') { %> | |
| <td><%- item.afterValue %></td> | |
| <% } else { %> | |
| <td><%- item.beforeValue %> > <%- item.afterValue %><% if (typeof(item.displayOtherValue) === 'string') { %><%- item.displayOtherValue %><% } %></br> | |
| <% if(item.otherValue != 'null' && typeof(item.otherValue) === 'string' && item.processor == 'member') { %><%- item.otherValue %><% } %> | |
| <% if(item.memberLifeEventValue != 'null' && typeof(item.memberLifeEventValue) === 'string' && item.updateColumn == '개인정보유효기간' && item.beforeValue !== '999' && item.afterValue === '999') { %><%- item.memberLifeEventValue %><% } %> | |
| </td> | |
| <% } %> | |
| </tr> | |
| <% } %> | |
| <%});%> | |
| </script> | |
| <script id="history-pagination-template2" type="text/template"> | |
| <nav> | |
| <ul class="pagination pagination-sm"> | |
| <% for(var i = page.start; i < page.end; i++) { %> <% if(i === (page.now *1)){ %> | |
| <li class="active"> | |
| <span><%- i %></span> | |
| </li> | |
변경 후_member_view_history.php
| <section class="ncua-content ncua-block-container ncua-member-view-history"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <span class="ncua-block-header__title">회원정보 수정이력</span> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-search-result"> | |
| <form id="frmHistory" method="get"> | |
| <input type="hidden" name="pageNum"/> | |
| <div class="ncua-search-result__content"> | |
| <div class="ncua-search-result__actions"> | |
| <div class="ncua-search-result__actions-select"> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <?= gd_select_box_by_page_view_count(Request::get()->get('pageNum', 10), null, null, 'ncua-select__tag'); ?> | |
| </span> | |
| </span> | |
| </div> | |
| </div> | |
| <div class="ncua-table ncua-table--horizontal"> | |
| <table> | |
| <colgroup> | |
| <col width="80px"/> | |
| <col width="200px"/> | |
| <col width="100px"/> | |
| <col width="100px"/> | |
| <col width="278px"/> | |
| <col width="*"/> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th><div>번호</div></th> | |
| <th><div>변경일자</div></th> | |
| <th><div>처리자</div></th> | |
| <th><div>IP주소</div></th> | |
| <th><div>변경항목</div></th> | |
| <th><div>변경내용</div></th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div class="ncua-pagination" id="div-pagination"></div> | |
| </form> | |
| </div> | |
| </div> | |
| </section> | |
| <script type="text/template" id="history-row-template2"> | |
| <% var rows = _.filter(data || [], function(item){ return item.updateColumn !== '최종구매일'; }); %> | |
| <% if(rows.length === 0) { %> | |
| <tr> | |
| <td colspan="6" height="50" class="no-data"><div>등록된 게시물이 없습니다.</div></td> | |
| </tr> | |
| <% } %> | |
| <% _.each(rows, function(item){ %> | |
| <tr> | |
| <td><div><%- item.idx %></div></td> | |
| <td><div><%- item.regDt %></div></td> | |
| <td><div><%- item.processor %><%- item.deleteText %></div></td> | |
| <td><div><%- item.processorIp %></div></td> | |
| <td><div><%- item.updateColumn %></div></td> | |
| <% if(item.updateColumn === '비밀번호') { %> | |
| <td><div><%- item.afterValue %></div></td> | |
| <% } else { %> | |
| <td><div><%- item.beforeValue %> > <%- item.afterValue %><% if (typeof(item.displayOtherValue) === 'string') { %><%- item.displayOtherValue %><% } %><br/> | |
| <% if(item.otherValue != 'null' && typeof(item.otherValue) === 'string' && item.processor == 'member') { %><%- item.otherValue %><% } %> | |
| <% if(item.memberLifeEventValue != 'null' && typeof(item.memberLifeEventValue) === 'string' && item.updateColumn == '개인정보유효기간' && item.beforeValue !== '999' && item.afterValue === '999') { %><%- item.memberLifeEventValue %><% } %> | |
| </div></td> | |
| <% } %> | |
| </tr> | |
| <%});%> | |
| </script> | |
| <script id="history-pagination-template2" type="text/template"> | |
| <nav> | |
| <ul class="pagination pagination-sm"> | |
| <% for(var i = page.start; i <= page.end; i++) { %> <% if(i === (page.now *1)){ %> | |
| <li class="active"> | |
| <span><%- i %></span> | |
| </li> | |
변경 전_member_view_other.php
| <div class="table-title gd-help-manual">부가정보</div> | |
| <div class="input_wrap form-inline"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : 'width-3xl' ?>"/> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : '' ?>"/> | |
| </colgroup> | |
| <tr> | |
| <th>팩스번호</th> | |
| <td> | |
| <span title="팩스번호를 입력해주세요!"> | |
| <input type="text" name="fax" value="<?= $data['fax'] ?>" maxlength="12" class="form-control js-number-only width-md"/> | |
| </span> | |
| </td> | |
| <th>직업</th> | |
| <td class="input_area" colspan="3"> | |
| <?= gd_select_box('job', 'job', $joinField['job']['data'], null, $data['job'], '선택'); ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>성별</th> | |
| <td> | |
| <label class="radio-inline"> | |
| <input type="radio" name="sexFl" value="m" <?= $checked['sexFl']['m']; ?>> | |
| 남자 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="sexFl" value="w" <?= $checked['sexFl']['w']; ?>> | |
| 여자 | |
| </label> | |
| </td> | |
| <th>생일</th> | |
| <td> | |
| <?= gd_select_box( | |
| 'calendarFl', 'calendarFl', [ | |
| 's' => '양력', | |
| 'l' => '음력', | |
| ], null, $data['calendarFl'], '선택' | |
| ); ?> | |
| <span title="생일을 입력해주세요!"> | |
| <input type="text" class="js-datepicker" name="birthDt" | |
| value="<?= $data['birthDt']; ?>"/> | |
| </span> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>결혼여부</th> | |
| <td> | |
| <label class="radio-inline"> | |
| <input type="radio" name="marriFl" value="n" | |
| data-target="input[name=marriDate]" <?= $checked['marriFl']['n']; ?>> | |
| 미혼 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="marriFl" value="y" | |
| data-target="input[name=marriDate]" <?= $checked['marriFl']['y']; ?>> | |
| 기혼 | |
| </label> | |
| </td> | |
| <th>결혼기념일</th> | |
| <td> | |
| <span title="결혼기념일을 입력해주세요!"> | |
| <input type="text" class="js-datepicker" name="marriDate" | |
| value="<?= $data['marriDate']; ?>"/> | |
| </span> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>추천인아이디</th> | |
| <td> | |
| <span id="recomm" title="추천인 아이디를 입력해주세요!"> | |
| <?php if (empty(gd_isset($data['recommId'], ''))) { ?> | |
| <input type="text" name="recommId" id="recommId" class="form-control error" | |
| value="<?= gd_isset($data['recommId'], ''); ?>"/> | |
| <input type="hidden" name="chkRecommendId" value=""/> | |
| <input type="button" id="btnRecommendCheck" value="확인" class="btn btn-gray btn-sm"/> | |
| <?php } else { | |
| echo gd_isset($data['recommId'], ''); | |
| echo '<input type="hidden" name="recommId" value="' . gd_isset($data['recommId']) . '"/>'; | |
| ?> | |
| <?php } ?> | |
| </span> | |
| <span id="recommIdMsg" class="input_error_msg"></span> | |
| </td> | |
| <th>추천받은횟수</th> | |
| <td><?= gd_isset($data['recommendCnt'], '0'); ?>회</td> | |
| </tr> | |
| <tr> | |
| <th>관심분야</th> | |
| <td class="input_area" colspan="3"> | |
| <?= gd_check_box('interest[]', $joinField['interest']['data'], $data['interest'], $checkBoxRow) ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>개인정보유효기간</th> | |
| <td class="input_area" colspan="3"> | |
| <label class="radio-inline"> | |
| <input type="radio" name="expirationFl" value="1" <?= $checked['expirationFl']['1']; ?>> | |
| 1년 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="expirationFl" value="3" <?= $checked['expirationFl']['3']; ?>> | |
| 3년 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="expirationFl" value="5" <?= $checked['expirationFl']['5']; ?>> | |
| 5년 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="expirationFl" value="999" <?= $checked['expirationFl']['999']; ?>> | |
| 탈퇴 시 <?= $data['lifeMemberConversionDt']; ?> | |
| </label> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>남기는 말씀</th> | |
| <td class="input_area" colspan="3"> | |
| <span title="메모를 작성해 주세요!"> | |
| <textarea name="memo" rows="5" cols="" | |
| class="form-control width90p js-maxlength"><?= $data['memo']; ?></textarea> | |
| </span> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
| <?php if (gd_count($joinField['ex']) > 0) { ?> | |
| <div class="table-title gd-help-manual"> | |
| 추가정보 | |
| </div> | |
| <div class="input_wrap form-inline"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : 'width-3xl' ?>"/> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : '' ?>"/> | |
| </colgroup> | |
| <?= $htmlExtra; ?> | |
| </table> | |
| </div> | |
| <?php } ?> | |
| <div class="table-title gd-help-manual"> | |
| 개인정보 수집·이용 선택동의 내역 | |
| </div> | |
| <div class="form-inline"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col/> | |
| </colgroup> | |
| <tr> | |
| <th>개인정보<br/>수집·이용</th> | |
| <td> | |
| <?php | |
| if (isset($data['privateApprovalOptionFl']) && is_array($data['privateApprovalOptionFl']) && isset($privateApprovalOption)) { | |
| foreach ($privateApprovalOption as $index2 => $item2) { | |
| if($data['privateApprovalOptionFl'][$item2['sno']] == 'y'){ | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의함</div>'; | |
| } elseif ($data['privateApprovalOptionFl'][$item2['sno']] == 'n') { | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의안함</div>'; | |
| } | |
| } | |
| } else { | |
| echo '사용안함'; | |
| } | |
| ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>개인정보 취급위탁</th> | |
| <td> | |
| <?php | |
| if (isset($data['privateConsignFl']) && is_array($data['privateConsignFl']) && isset($privateConsign)) { | |
| foreach ($privateConsign as $index2 => $item2) { | |
| if($data['privateConsignFl'][$item2['sno']] == 'y'){ | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의함</div>'; | |
| } elseif ($data['privateConsignFl'][$item2['sno']] == 'n') { | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의안함</div>'; | |
| } | |
| } | |
| } else { | |
| echo '사용안함'; | |
| } | |
| ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>개인정보<br/>제3자 제공</th> | |
| <td> | |
| <?php | |
| if (isset($data['privateOfferFl']) && is_array($data['privateOfferFl']) && isset($privateOffer)) { | |
| foreach ($privateOffer as $index2 => $item2) { | |
| if($data['privateOfferFl'][$item2['sno']] == 'y'){ | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의함</div>'; | |
| } elseif ($data['privateOfferFl'][$item2['sno']] == 'n') { | |
| echo '<div>- ' . $item2['informNm'] . ' : 동의안함</div>'; | |
| } | |
| } | |
| } else { | |
| echo '사용안함'; | |
| } | |
| ?> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
변경 후_member_view_other.php
| <section class="ncua-block-container"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <div class="ncua-block-header__title-area"> | |
| <span class="ncua-block-header__title">부가정보</span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 240px;"/> | |
| <col /> | |
| </colgroup> | |
| <!-- 팩스 번호 --> | |
| <tr> | |
| <th><div data-tooltip-seq="025">팩스번호</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="fax" value="<?= $data['fax'] ?>" maxlength="12" class="js-number-only" title="팩스번호를 입력해주세요!" placeholder="'-' 없이 입력하세요."/> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| <!-- 직업 --> | |
| <tr> | |
| <th><div data-tooltip-seq="026">직업</div></th> | |
| <td><div> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <?= gd_select_box('job', 'job', $joinField['job']['data'], null, $data['job'], '선택', null, 'ncua-select__tag'); ?> | |
| </span> | |
| </span> | |
| </div></td> | |
| </tr> | |
| <!-- 성별 --> | |
| <tr> | |
| <th><div data-tooltip-seq="027">성별</div></th> | |
| <td><div class="ncua-flex-gap"> | |
| <!-- TODO(개발자 확인): '선택안함'(sexFl value="") 신규 추가. checked 하드코딩이라 저장값과 무관하게 항상 선택됨 → $checked['sexFl'] 기반 조건 처리 필요. BE에서 빈 값('') 저장/표시 처리 확인 필요 --> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="sexFl" value="" checked /> | |
| </span> | |
| <span class="ncua-radio-field__text">선택안함</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="sexFl" value="m" <?= $checked['sexFl']['m']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">남자</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="sexFl" value="w" <?= $checked['sexFl']['w']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">여자</span> | |
| </label> | |
| </div></td> | |
| </tr> | |
| <!-- 생일 --> | |
| <tr> | |
| <th><div data-tooltip-seq="028">생일</div></th> | |
| <td><div class="ncua-flex ncua-align-items-center ncua-gap-8"> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <?= gd_select_box('calendarFl', 'calendarFl', ['s' => '양력', 'l' => '음력'], null, $data['calendarFl'], '선택', null, 'ncua-select__tag'); ?> | |
| </span> | |
| </span> | |
| <div id="datepicker-birthday-container"></div> | |
| </div></td> | |
| </tr> | |
| <!-- 결혼여부 --> | |
| <tr> | |
| <th><div data-tooltip-seq="029">결혼여부</div></th> | |
| <td><div class="ncua-flex-gap"> | |
| <!-- TODO(개발자 확인): '선택안함'(marriFl value="n") 신규 추가. 미혼과 value="n"이 동일해 BE에서 구분 불가 + checked 하드코딩. 선택안함 전용 값/처리 방식 확인 필요 --> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="marriFl" value="n" data-target="input[name=marriDate]" checked /> | |
| </span> | |
| <span class="ncua-radio-field__text">선택안함</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="marriFl" value="n" data-target="input[name=marriDate]" <?= $checked['marriFl']['n']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">미혼</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="marriFl" value="y" data-target="input[name=marriDate]" <?= $checked['marriFl']['y']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">기혼</span> | |
| </label> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="030">결혼기념일</div></th> | |
| <td><div> | |
| <div id="datepicker-marriage-container"></div> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="031">추천인아이디</div></th> | |
| <td><div class="ncua-gap-4"> | |
| <span id="recomm"> | |
| <?php if (empty(gd_isset($data['recommId'], ''))) { ?> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="recommId" id="recommId" class="error" value="<?= gd_isset($data['recommId'], ''); ?>" title="추천인 아이디를 입력해주세요!" placeholder="추천인 아이디를 입력하세요."/> | |
| </div> | |
| </div> | |
| </div> | |
| <input type="hidden" name="chkRecommendId" value=""/> | |
| <button type="button" id="btnRecommendCheck" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">확인</button> | |
| <?php } else { | |
| echo gd_isset($data['recommId'], ''); | |
| echo '<input type="hidden" name="recommId" value="' . gd_isset($data['recommId']) . '"/>'; | |
| } ?> | |
| </span> | |
| <span id="recommIdMsg" class="input_error_msg"></span> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="032">추천받은횟수</div></th> | |
| <td><div><?= gd_isset($data['recommendCnt'], '0'); ?>회</div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="033">관심분야</div></th> | |
| <td><div class="ncua-flex-gap"> | |
| <?= gd_check_box_ncua('interest[]', $joinField['interest']['data'] ?? [], $data['interest'], $checkBoxRow ?? 0) ?> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="034">개인정보유효기간</div></th> | |
| <td><div class="ncua-flex-gap"> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="expirationFl" value="1" <?= $checked['expirationFl']['1']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">1년</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="expirationFl" value="3" <?= $checked['expirationFl']['3']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">3년</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="expirationFl" value="5" <?= $checked['expirationFl']['5']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">5년</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="expirationFl" value="999" <?= $checked['expirationFl']['999']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">탈퇴 시 <?= $data['lifeMemberConversionDt']; ?></span> | |
| </label> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="035">남기는 말씀</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--textarea ncua-input--textarea--xs"> | |
| <textarea class="ncua-input__textarea" name="memo" rows="5" title="메모를 작성해 주세요!" placeholder="내용을 입력하세요."><?= $data['memo']; ?></textarea> | |
| </div> | |
| </div></td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <?php if (gd_count($joinField['ex']) > 0) { ?> | |
| <section class="ncua-block-container"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <div class="ncua-block-header__title-area"> | |
| <span class="ncua-block-header__title">추가정보</span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <!-- tr/th/td 행 전체는 makeExtraField(BE) 생성물. 사용 중인 추가정보 항목 1개당 tr 1행(th + td) 출력 --> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 240px;"/> | |
| <col /> | |
| </colgroup> | |
| <?= $htmlExtra; ?> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <?php } ?> | |
| <section class="ncua-block-container"> | |
| <header class="ncua-block-header"> | |
| <div class="ncua-block-header__row"> | |
| <div class="ncua-block-header__title-area"> | |
| <span class="ncua-block-header__title">개인정보 수집·이용 선택동의 내역</span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 240px;"/> | |
| <col /> | |
| </colgroup> | |
| <?php foreach (($privateAgreementRows ?? []) as $row): ?> | |
| <tr> | |
| <th> | |
| <div<?= !empty($row['tooltipSeq']) ? ' data-tooltip-seq="' . $row['tooltipSeq'] . '"' : '' ?>><?= $row['title'] ?></div> | |
| </th> | |
| <td> | |
| <?php foreach ($row['lines'] as $line): ?> | |
| <div><?= $line ?></div> | |
| <?php endforeach; ?> | |
| </td> | |
| </tr> | |
| <?php endforeach; ?> | |
| <tr> | |
| <th><div data-tooltip-seq="040">광고성 수신 동의</div></th> | |
| <td> | |
| <?php foreach (($advertisingReceiveLines ?? []) as $line): ?> | |
| <div><?= $line ?></div> | |
| <?php endforeach; ?> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <script type="text/javascript"> | |
| document.addEventListener('DOMContentLoaded', function () { | |
| const birthDatePicker = new ncua.DatePicker(document.querySelector('#datepicker-birthday-container'), { | |
| size: 'xs', | |
| datePickerOptions: [{ | |
| element: 'start-date', | |
| attrName: 'birthDt', | |
| options: { | |
| mode: 'single', | |
| static: true, | |
| dateFormat: 'Y-m-d', | |
| clickOpens: true, | |
| allowInvalidPreload: true, | |
| allowInput: true, | |
| locale: 'ko', | |
| }, | |
| }], | |
| }); | |
| <?php if (!empty($data['birthDt'])) { ?> | |
| birthDatePicker.setDate(["<?= $data['birthDt']; ?>"]); | |
| <?php } ?> | |
| const marriageContainer = document.querySelector('#datepicker-marriage-container'); | |
| const marriageDatePicker = new ncua.DatePicker(marriageContainer, { | |
| size: 'xs', | |
| datePickerOptions: [{ | |
| element: 'start-date', | |
| attrName: 'marriDate', | |
| options: { | |
| mode: 'single', | |
| static: true, | |
| dateFormat: 'Y-m-d', | |
| clickOpens: true, | |
| allowInvalidPreload: true, | |
| allowInput: true, | |
| locale: 'ko', | |
| }, | |
| }], | |
| }); | |
| <?php if (!empty($data['marriDate'])) { ?> | |
| marriageDatePicker.setDate(["<?= $data['marriDate']; ?>"]); | |
| <?php } ?> | |
| // 결혼여부(marriFl)에 따라 결혼기념일 datepicker 활성/비활성 (기혼=y일 때만 활성) | |
| const syncMarriageDisabled = function () { | |
| const married = document.querySelector('input[name="marriFl"]:checked'); | |
| const isEnabled = !!(married && married.value === 'y'); | |
| const ncuaDatePicker = marriageContainer.querySelector('.ncua-date-picker'); | |
| document.querySelectorAll('[name="marriDate"]').forEach(function (el) { | |
| el.disabled = !isEnabled; | |
| }); | |
| if (ncuaDatePicker) { | |
| ncuaDatePicker.classList.toggle('ncua-date-picker--disabled', !isEnabled); | |
| } | |
| }; | |
| syncMarriageDisabled(); | |
| document.querySelectorAll('input[name="marriFl"]').forEach(function (el) { | |
| el.addEventListener('change', syncMarriageDisabled); | |
| }); | |
| }); | |
| </script> | |
변경 전_member_view.php
| <div class="table-title gd-help-manual"> | |
| 기본정보 | |
| </div> | |
| <div class="form-inline"> | |
| <table class="table table-cols"> | |
| <colgroup> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : 'width-3xl' ?>"/> | |
| <col class="width-sm"/> | |
| <col class="<?= (!empty($widthClass)) ? $widthClass : '' ?>"/> | |
| </colgroup> | |
| <tr> | |
| <th>회원구분</th> | |
| <td <?= $data['mallSno'] > 0 ? '' : 'colspan="3"' ?>> | |
| <label class="radio-inline"> | |
| <input type="radio" name="memberFl" value="personal" | |
| data-target=".div-business" <?= $checked['memberFl']['personal']; ?>/> | |
| 개인회원 | |
| </label> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <label class="radio-inline"> | |
| <input type="radio" name="memberFl" value="business" | |
| data-target=".div-business" <?= $checked['memberFl']['business']; ?>/> | |
| 사업자회원 | |
| </label> | |
| <?php } ?> | |
| </td> | |
| <?php if ($data['mallSno'] > 0) { ?> | |
| <th>상점구분</th> | |
| <td> | |
| <span class="flag flag-16 flag-<?= gd_isset($gGlobal['mallList'][$data['mallSno']]['domainFl'], 'kr'); ?>"></span><?= gd_isset($gGlobal['mallList'][$data['mallSno']]['mallName'], '기준몰'); ?> | |
| </td> | |
| <?php } ?> | |
| </tr> | |
| <tr> | |
| <th>등급</th> | |
| <td> | |
| <?= gd_select_box_by_group_list($data['groupSno'], '등급선택'); ?> | |
| <span id="groupSnoMsg" class="input_error_msg"></span> | |
| <?php if ($mode != 'register') { ?> | |
| <div>수정일: | |
| <span class="font-num"><?= $data['groupModDt']; ?></span> | |
| </div> | |
| <?php } ?> | |
| </td> | |
| <th>승인</th> | |
| <td> | |
| <div class="radio"> | |
| <label class="radio-inline"> | |
| <input type="radio" name="appFl" value="y" <?= $checked['appFl']['y']; ?>/> | |
| 승인 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="appFl" value="n" <?= $checked['appFl']['n']; ?>/> | |
| 미승인 | |
| </label> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th class="require">아이디</th> | |
| <td> | |
| <?php if ($mode == 'register') { ?> | |
| <span title="이용하실 아이디를 입력해주세요!"> | |
| <input type="text" name="memId" id="memId" value="" class="form-control error" data-pattern="gdMemberId"/> | |
| <button type="button" id="overlap_memId" class="btn btn-gray btn-sm">중복확인</button> | |
| </span> | |
| <?php } else { ?> | |
| <input type="hidden" name="memId" id="memId" class="" value="<?= $data['memId'] ?>"/> | |
| <strong><?= $data['memId'] ?></strong> | |
| <?= gd_get_third_party_icon_web_path($data['snsTypeFl']); ?> | |
| <?php if($data['simpleJoinFl'] == 'order') { ?><span class="text-blue">(주문 간단 가입)</span><?php } ?> | |
| <?php if($data['simpleJoinFl'] == 'push') { ?><span class="text-blue">(가입 유도 푸시)</span><?php } ?> | |
| <?php } ?> | |
| </td> | |
| <th>닉네임</th> | |
| <td> | |
| <span title="별명을 입력해주세요!"> | |
| <input type="text" name="nickNm" id="nickNm" value="<?= $data['nickNm'] ?>" | |
| class="form-control width-sm error"> | |
| </span> | |
| <button type="button" id="overlap_nickNm" class="btn btn-gray btn-sm">중복확인</button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th class="require">이름</th> | |
| <td colspan="<?= $hidePasswordBlock ? 3 : 1 ?>"> | |
| <span title="이름을 입력해주세요!"> | |
| <input type="text" name="memNm" id="memNm" value="<?= $data['memNm'] ?>" | |
| class="form-control width-sm" data-pattern="<?= (($data['mallSno'] > $gGlobal['defaultMallSno'])) ? 'gdEngKor' : 'gdMemberNmGlobal' ?>" maxlength="20"> | |
| </span> | |
| <?php if ($joinField['pronounceName']['use'] == 'y') { ?> | |
| <input type="text" name="pronounceName" id="pronounceName" value="<?= $data['pronounceName'] ?>" | |
| class="form-control width-sm" maxlength="20" placeholder="발음 표시" data-pattern="<?= (($data['mallSno'] > 1)) ? 'gdEngKor' : 'gdMemberNmGlobal' ?>"> | |
| <?php } ?> | |
| </td> | |
| <?php if (!$hidePasswordBlock) : ?> | |
| <th class="require">비밀번호</th> | |
| <td> | |
| <span title="비밀번호를 입력해주세요!"> | |
| <input type="password" name="memPw" value="" class="form-control width-sm js-maxlength" | |
| placeholder="비밀번호입력" maxlength="16"> | |
| | |
| <input type="password" name="memPwRe" value="" class="form-control width-sm js-maxlength" | |
| placeholder="비밀번호확인" maxlength="16" style="margin-left: 40px"> | |
| </span> | |
| <?php | |
| if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { | |
| echo '<p class="notice-danger notice-info">*영문대문자/영문소문자/숫자/특수문자 중 2개 이상 포함, 10~16자리 이하로 설정할 수 있습니다.</p>'; | |
| } else { | |
| if ($joinField['passwordCombineFl'] == 'engNum') { | |
| echo '<p class="notice-danger notice-info">*영문대문자/영문소문자/숫자 중 2개 이상 포함,'; | |
| } elseif ($joinField['passwordCombineFl'] == 'engNumEtc') { | |
| echo '<p class="notice-danger notice-info">*영문대문자/영문소문자/숫자/특수문자 중 3개 이상 포함,'; | |
| } else { | |
| echo '<p class="notice-danger notice-info">*영문대문자/영문소문자 or 숫자,'; | |
| } | |
| echo ' ' . $joinField['memPw']['minlen'] . '~' . $joinField['memPw']['maxlen'] . '자리 이하로 설정할 수 있습니다.</p>'; | |
| } ?> | |
| </td> | |
| <?php endif; ?> | |
| </tr> | |
| <?php if ($mode != 'register') { ?> | |
| <tr> | |
| <th>주문금액</th> | |
| <td colspan="3"><?= gd_currency_display($data['saleAmt']); ?></td> | |
| </tr> | |
| <tr> | |
| <th>마일리지</th> | |
| <td><?= gd_money_format($data['mileage']) . gd_display_mileage_unit() ?></td> | |
| <th>예치금</th> | |
| <td><?= gd_money_format($data['deposit']) . gd_display_deposit('unit') ?></td> | |
| </tr> | |
| <tr> | |
| <th>회원가입일</th> | |
| <td><?= $data['entryDt'] ?></td> | |
| <th>가입경로</th> | |
| <td><?= $data['entryPath'] ?></td> | |
| </tr> | |
| <tr> | |
| <th>최종로그인일</th> | |
| <td><?= $data['lastLoginDt'] ?></td> | |
| <th>방문횟수</th> | |
| <td><?= $data['loginCnt'] ?></td> | |
| </tr> | |
| <tr> | |
| <th>휴면해제일</th> | |
| <td colspan="3"><?= $data['sleepWakeDt']; ?></td> | |
| </tr> | |
| <?php } ?> | |
| <tr> | |
| <th>이메일</th> | |
| <td> | |
| <div class="form-inline mgb5"> | |
| <input type="hidden" name="chkEmail" value=""/> | |
| <span title="이메일을 입력해주세요!"> | |
| <input type="text" id="emailAddress" name="email[]" value="<?= $data['email'][0] ?>" | |
| class="form-control width-sm"> | |
| @ | |
| </span> | |
| <span title="이메일을 입력해주세요!"> | |
| <input type="text" id="emailDomain" name="email[]" value="<?= $data['email'][1] ?>" | |
| class="form-control width-sm error"> | |
| </span> | |
| <?= gd_select_box_by_mail_domain('email_site', 'email_site', null, $data['email'][1], '직접입력'); ?> | |
| <button type="button" id="overlap_email" class="btn btn-gray btn-sm">중복확인</button> | |
| </div> | |
| <div class="form-inline"> | |
| <label class="checkbox-inline"> | |
| <input type="checkbox" name="maillingFl" value="y" data-default="" <?= $checked['maillingFl']['y']; ?>/> | |
| 정보/이벤트 MAIL 수신에 동의합니다. | |
| </label> | |
| </div> | |
| <p class="notice-danger notice-info">*수신동의설정 안내메일의 자동발송여부에 따라 회원정보의 수신동의설정 변경 시 해당 회원에게 안내메일이 자동 발송됩니다.</p> | |
| </td> | |
| <th>이메일<br/>수신동의/거부일</th> | |
| <td> | |
| <?php | |
| $mailLastReceiveAgreementDt = gd_isset($data['lastReceiveAgreementDt']['mail'], $data['entryDt']); | |
| $mailAgreementView = '동의 : ' . $mailLastReceiveAgreementDt; | |
| if (gd_isset($data['lastNotificationDt']['mail'], '-') != '-') { | |
| $mailAgreementView .= '<br/>(수신동의여부 확인메일 발송<br/> : ' . $data['lastNotificationDt']['mail'] . ')'; | |
| } | |
| ?> | |
| <?= $data['maillingFl'] == 'y' ? $mailAgreementView : '거부 : ' . gd_date_format('Y-m-d', $mailLastReceiveAgreementDt); ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>휴대폰번호</th> | |
| <td> | |
| <div class="form-inline mgb5"> | |
| <?php | |
| $cellPhoneCallPrefixAttributes = [ | |
| 'id' => 'cellPhoneCountryCode', | |
| 'name' => 'cellPhoneCountryCode', | |
| ]; | |
| if ($mode != 'register' && $data['mallSno'] != $gGlobal['defaultMallSno']) { | |
| echo gd_select_box_by_call_prefix($cellPhoneCallPrefixAttributes, $data['cellPhoneCountryCode']); | |
| } | |
| ?> | |
| <span title="휴대폰번호를 입력해주세요!"> | |
| <input type="text" name="cellPhone" value="<?= $data['cellPhone'] ?>" maxlength="12" class="form-control js-number-only width-md"/> | |
| </span> | |
| </div> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <div class="form-inline"> | |
| <span id="cellPhoneMsg" class="input_error_msg"></span> | |
| <label class="checkbox-inline"> | |
| <input type="checkbox" name="smsFl" value="y" <?= $checked['smsFl']['y']; ?>> | |
| 정보/이벤트 SMS 수신에 동의합니다. | |
| </label> | |
| </div> | |
| <p class="notice-danger notice-info">*수신동의설정 안내메일의 자동발송여부에 따라 회원정보의 수신동의설정 변경 시 해당 회원에게 SMS가 자동 발송됩니다.</p> | |
| <?php } ?> | |
| </td> | |
| <th>SMS<br/>수신동의/거부일</th> | |
| <td> | |
| <?php | |
| $smsLastReceiveAgreementDt = gd_isset($data['lastReceiveAgreementDt']['sms'], $data['entryDt']); | |
| $smsAgreementView = '동의 : ' . $smsLastReceiveAgreementDt; | |
| if (gd_isset($data['lastNotificationDt']['sms'], '-') != '-') { | |
| $smsAgreementView .= '<br/>(수신동의여부 확인SMS 발송<br/> : ' . $data['lastNotificationDt']['sms'] . ')'; | |
| } | |
| ?> | |
| <?= $data['smsFl'] == 'y' ? $smsAgreementView : '거부 : ' . gd_date_format('Y-m-d', $smsLastReceiveAgreementDt); ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>주소</th> | |
| <td colspan="3"> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <div class="form-inline mgb5"> | |
| <span title="우편번호를 입력해주세요!"> | |
| <input type="text" size="6" maxlength="5" name="zonecode" class="form-control js-number" | |
| data-number="5" | |
| value="<?= $data['zonecode'] ?>"/> | |
| <input type="hidden" name="zipcode" value="<?= $data['zipcode'] ?>"/> | |
| <span id="zipcodeText" class="number <?php if (strlen($data['zipcode']) != 7) { | |
| echo 'display-none'; | |
| } ?>">(<?php echo $data['zipcode']; ?>) | |
| </span> | |
| </span> | |
| <input type="button" | |
| onclick="postcode_search('zonecode', 'address', 'zipcode');" | |
| value="우편번호찾기" class="btn btn-gray btn-sm"/> | |
| </div> | |
| <div class="form-inline"> | |
| <span title="주소를 입력해주세요!"> | |
| <input type="text" name="address" id="address" | |
| class="form-control width-2xl" | |
| value="<?= $data['address']; ?>"/> | |
| </span> | |
| <span title="상세주소를 입력해주세요!"> | |
| <input type="text" name="addressSub" id="addressSub" | |
| class="form-control width-2xl" | |
| value="<?= $data['addressSub']; ?>"/> | |
| </span> | |
| </div> | |
| <?php } ?> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>전화번호</th> | |
| <td colspan="3"> | |
| <div class="form-inline"> | |
| <?php | |
| $phoneCallPrefixAttributes = [ | |
| 'id' => 'phoneCountryCode', | |
| 'name' => 'phoneCountryCode', | |
| ]; | |
| if ($mode != 'register' && $data['mallSno'] != $gGlobal['defaultMallSno']) { | |
| gd_select_box_by_call_prefix($phoneCallPrefixAttributes, $data['phoneCountryCode']); | |
| } | |
| ?> | |
| <span title="전화번호를 입력해주세요!"> | |
| <input type="text" name="phone" value="<?= $data['phone'] ?>" maxlength="12" class="form-control js-number-only width-md"/> | |
| </span> | |
| </div> | |
| </td> | |
| </tr> | |
| </table> | |
| </div> | |
변경 후_member_view.php
| <section class="ncua-block-container"> | |
| <header class="ncua-block-header ncua-block-header--is-required"> | |
| <div class="ncua-block-header__row"> | |
| <div class="ncua-block-header__title-area"> | |
| <span class="ncua-block-header__title">기본정보</span> | |
| </div> | |
| <div class="ncua-block-header__action-area"> | |
| <span class="ncua-block-header__required-notice"><span class="ncua-block-header__required-notice--red">* 는 필수 입력</span><span class="ncua-block-header__required-notice--gray"> 항목입니다.</span></span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="ncua-block-container__body"> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <colgroup> | |
| <col style="width: 240px;"/> | |
| <col /> | |
| </colgroup> | |
| <!-- 회원구분 --> | |
| <tr> | |
| <th><div data-tooltip-seq="001">회원구분</div></th> | |
| <td><div class="ncua-flex-gap"> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="memberFl" value="personal" | |
| data-target=".div-business" <?= $checked['memberFl']['personal']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">개인회원</span> | |
| </label> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="memberFl" value="business" | |
| data-target=".div-business" <?= $checked['memberFl']['business']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">사업자회원</span> | |
| </label> | |
| <?php } ?> | |
| </div></td> | |
| </tr> | |
| <!-- 상점구분 --> | |
| <?php if ($data['mallSno'] > 0) { ?> | |
| <tr> | |
| <th><div>상점구분</div></th> | |
| <td><div class="ncua-gap-8"> | |
| <span class="flag flag-16 flag-<?= gd_isset($gGlobal['mallList'][$data['mallSno']]['domainFl'], 'kr'); ?>"></span><?= gd_isset($gGlobal['mallList'][$data['mallSno']]['mallName'], '기준몰'); ?> | |
| </div></td> | |
| </tr> | |
| <?php } ?> | |
| <!-- 등급 --> | |
| <tr> | |
| <th><div data-tooltip-seq="002">등급</div></th> | |
| <td><div class="ncua-gap-8"> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <?= gd_select_box('groupSno', 'groupSno', \Component\Member\Group\Util::getGroupName(), null, $data['groupSno'], '등급선택', null, 'ncua-select__tag'); ?> | |
| </span> | |
| </span> | |
| <span id="groupSnoMsg" class="input_error_msg"></span> | |
| <?php if ($mode != 'register') { ?> | |
| <div>수정일: | |
| <span class="font-num"><?= $data['groupModDt']; ?></span> | |
| </div> | |
| <?php } ?> | |
| </div></td> | |
| </tr> | |
| <!-- 승인 --> | |
| <tr> | |
| <th><div data-tooltip-seq="003">승인</div></th> | |
| <td> | |
| <div class="ncua-flex-gap"> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="appFl" value="y" <?= $checked['appFl']['y']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">승인</span> | |
| </label> | |
| <label class="ncua-radio-field ncua-radio-field--xs has-text"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="appFl" value="n" <?= $checked['appFl']['n']; ?>/> | |
| </span> | |
| <span class="ncua-radio-field__text">미승인</span> | |
| </label> | |
| </div> | |
| </td> | |
| </tr> | |
| <!-- 아이디 --> | |
| <tr> | |
| <th class="ncua-required"><div data-tooltip-seq="004">아이디</div></th> | |
| <td><div class="ncua-gap-4"> | |
| <?php if ($mode == 'register') { ?> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="memId" id="memId" value="" class="error" data-pattern="gdMemberId" placeholder="영문, 숫자, 특수문자(-),(_),(.),(@), 4~50자"/> | |
| </div> | |
| </div> | |
| </div> | |
| <button type="button" id="overlap_memId" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">중복확인</button> | |
| <?php } else { ?> | |
| <input type="hidden" name="memId" id="memId" class="" value="<?= $data['memId'] ?>"/> | |
| <strong><?= $data['memId'] ?></strong> | |
| <?= gd_get_third_party_icon_web_path($data['snsTypeFl']); ?> | |
| <?php if($data['simpleJoinFl'] == 'order') { ?><span class="text-blue">(주문 간단 가입)</span><?php } ?> | |
| <?php if($data['simpleJoinFl'] == 'push') { ?><span class="text-blue">(가입 유도 푸시)</span><?php } ?> | |
| <?php } ?> | |
| </div></td> | |
| </tr> | |
| <!-- 닉네임 --> | |
| <tr> | |
| <th><div data-tooltip-seq="005">닉네임</div></th> | |
| <td><div class="ncua-gap-4"> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="nickNm" id="nickNm" value="<?= $data['nickNm'] ?>" class="error" placeholder="닉네임을 입력하세요"> | |
| </div> | |
| </div> | |
| </div> | |
| <button type="button" id="overlap_nickNm" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">중복확인</button> | |
| </div></td> | |
| </tr> | |
| <!-- 이름 --> | |
| <tr> | |
| <th class="ncua-required"><div data-tooltip-seq="006">이름</div></th> | |
| <td><div> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="memNm" id="memNm" value="<?= $data['memNm'] ?>" data-pattern="<?= (($data['mallSno'] > $gGlobal['defaultMallSno'])) ? 'gdEngKor' : 'gdMemberNmGlobal' ?>" maxlength="20" title="이름을 입력해주세요!" placeholder="이름을 입력하세요."> | |
| </div> | |
| </div> | |
| </div> | |
| <?php if ($joinField['pronounceName']['use'] == 'y') { ?> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-320"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="pronounceName" id="pronounceName" value="<?= $data['pronounceName'] ?>" maxlength="20" placeholder="발음 표시" data-pattern="<?= (($data['mallSno'] > 1)) ? 'gdEngKor' : 'gdMemberNmGlobal' ?>"> | |
| </div> | |
| </div> | |
| </div> | |
| <?php } ?> | |
| </div></td> | |
| </tr> | |
| <!-- 비밀번호 --> | |
| <?php if (!$hidePasswordBlock) : ?> | |
| <tr> | |
| <th class="ncua-required"><div data-tooltip-seq="007">비밀번호</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start ncua-gap-8"> | |
| <div class="ncua-input ncua-input--xs"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content ncua-input-width-380"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="password" name="memPw" maxlength="<?php echo $joinField['memPw']['maxlen']; ?>" value="" class="js-member-pw" placeholder="<?= $passwordPlaceholder ?? '' ?>" data-charcount-key="memberPwText"> | |
| </div> </div> | |
| <div class="ncua-input__field-text-count" data-charcount-text="memberPwText"> | |
| <output class="ncua-input__field-text-count-current">0</output> | |
| <span>/<?php echo $joinField['memPw']['maxlen']; ?></span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <!-- 비밀번호 확인 --> | |
| <tr> | |
| <th class="ncua-required"><div data-tooltip-seq="008">비밀번호 확인</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start ncua-gap-8"> | |
| <div class="ncua-input ncua-input--xs"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content ncua-input-width-380"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="password" name="memPwRe" value="" class="js-re-member-pw" maxlength="<?php echo $joinField['memPw']['maxlen']; ?>" placeholder="<?= $passwordPlaceholder ?? '' ?>" data-charcount-key="reMemberPwText"> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count" data-charcount-text="reMemberPwText"> | |
| <output class="ncua-input__field-text-count-current">0</output> | |
| <span>/<?php echo $joinField['memPw']['maxlen']; ?></span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <?php endif; ?> | |
| <!-- 주문금액, 마일리지, 예치금, 회원가입일 --> | |
| <?php if ($mode != 'register') { ?> | |
| <tr> | |
| <th><div data-tooltip-seq="017">주문금액</div></th> | |
| <td><div><?= gd_currency_display($data['saleAmt']); ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="018">마일리지</div></th> | |
| <td><div><?= gd_money_format($data['mileage']) . gd_display_mileage_unit() ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="019">예치금</div></th> | |
| <td><div><?= gd_money_format($data['deposit']) . gd_display_deposit('unit') ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="020">회원가입일</div></th> | |
| <td><div><?= $data['entryDt'] ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="021">가입경로</div></th> | |
| <td><div><?= $data['entryPath'] ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="022">최종로그인일</div></th> | |
| <td><div><?= $data['lastLoginDt'] ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="023">방문횟수</div></th> | |
| <td><div><?= $data['loginCnt'] ?></div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="024">휴면해제일</div></th> | |
| <td><div><?= $data['sleepWakeDt']; ?></div></td> | |
| </tr> | |
| <?php } ?> | |
| <!-- 마케팅 목적 개인정보 수집 및 이용 동의 --> | |
| <?php if ($privateMarketingMemberUse): ?> | |
| <tr> | |
| <th><div data-tooltip-seq="009">마케팅 목적 개인정보 수집 및 이용 동의</div></th> | |
| <td><div> | |
| <label class="ncua-checkbox-field ncua-checkbox-field--xs has-text"> | |
| <span class="ncua-checkbox-input ncua-checkbox-input--xs ncua-checkbox-field__input"> | |
| <input type="checkbox" name="privateMarketingConsentOptionFl" value="y" <?= ($mode === 'register') ? 'disabled' : '' ?> <?= $checked['privateMarketingConsentOptionFl']['y']; ?>/> | |
| </span> | |
| <span class="ncua-checkbox-field__text">마케팅 목적 개인정보 수집 및 이용 동의</span> | |
| </label> | |
| </div></td> | |
| </tr> | |
| <tr> | |
| <th><div data-tooltip-seq="010">마케팅 목적 개인정보 수집 및 이용 동의/거부일</div></th> | |
| <td><div> | |
| <?= ($data['privateMarketingConsentOptionFl'] === 'y' ? '동의 : ' : '거부 : ') . ($data['privateMktAgreementDt'] ?? '-') ?> | |
| </div></td> | |
| </tr> | |
| <?php endif; ?> | |
| <!-- 이메일 --> | |
| <tr> | |
| <th><div data-tooltip-seq="011">이메일</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start ncua-gap-4"> | |
| <div class="ncua-flex ncua-gap-4"> | |
| <div class="ncua-flex ncua-align-items-center ncua-gap-8"> | |
| <input type="hidden" name="chkEmail" value=""/> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-150"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" id="emailAddress" name="email[]" value="<?= $data['email'][0] ?>" title="이메일을 입력해주세요!"> | |
| </div> | |
| </div> | |
| </div> | |
| @ | |
| <div class="ncua-input ncua-input--xs ncua-input-width-150"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" id="emailDomain" name="email[]" value="<?= $data['email'][1] ?>" class="error" title="이메일을 입력해주세요!"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <?= gd_select_box_by_mail_domain('email_site', 'email_site', null, $data['email'][1], '직접입력', null, 'ncua-select__tag'); ?> | |
| </span> | |
| </span> | |
| <button type="button" id="overlap_email" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray">중복확인</button> | |
| </div> | |
| <div> | |
| <label class="ncua-checkbox-field ncua-checkbox-field--xs has-text"> | |
| <span class="ncua-checkbox-input ncua-checkbox-input--xs ncua-checkbox-field__input"> | |
| <input type="checkbox" name="maillingFl" <?= ($mode === 'register') ? 'disabled' : '' ?> value="y" data-default="" <?= $checked['maillingFl']['y']; ?>/> | |
| </span> | |
| <span class="ncua-checkbox-field__text">마케팅 이메일 수신 동의</span> | |
| </label> | |
| </div> | |
| <p class="ncua-caution-text">수신동의설정 안내메일의 자동발송여부에 따라 회원정보의 수신동의설정 변경 시 해당 회원에게 안내메일이 자동 발송됩니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| <!-- 이메일 수신동의/거부일 --> | |
| <tr> | |
| <th><div data-tooltip-seq="012">이메일 수신동의/거부일</div></th> | |
| <td><div class="ncua-flex-column ncua-align-items-start"> | |
| <?php | |
| $mailLastReceiveAgreementDt = gd_isset($data['lastReceiveAgreementDt']['mail'], $data['entryDt']); | |
| $mailAgreementView = '동의 : ' . $mailLastReceiveAgreementDt; | |
| if (gd_isset($data['lastNotificationDt']['mail'], '-') != '-') { | |
| $mailAgreementView .= '<br/>(수신동의여부 확인메일 발송<br/> : ' . $data['lastNotificationDt']['mail'] . ')'; | |
| } | |
| ?> | |
| <?= $data['maillingFl'] == 'y' ? $mailAgreementView : '거부 : ' . $mailLastReceiveAgreementDt; ?> | |
| </div></td> | |
| </tr> | |
| <!-- 휴대폰번호 --> | |
| <tr> | |
| <th><div data-tooltip-seq="013">휴대폰번호</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start ncua-gap-4"> | |
| <div class="ncua-flex ncua-gap-4"> | |
| <?php if ($mode != 'register' && $data['mallSno'] != $gGlobal['defaultMallSno']): ?> | |
| <span class="ncua-select ncua-select--xs"> | |
| <span class="ncua-select__content"> | |
| <select class="ncua-select__tag" id="cellPhoneCountryCode" name="cellPhoneCountryCode"> | |
| <option value="">국가선택</option> | |
| <?php foreach ($callPrefixList as $code => $label): ?> | |
| <option value="<?= gd_htmlspecialchars($code) ?>"<?= $data['cellPhoneCountryCode'] === $code ? ' selected' : '' ?>><?= $label ?></option> | |
| <?php endforeach; ?> | |
| </select> | |
| </span> | |
| </span> | |
| <?php endif; ?> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-150"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="cellPhone" value="<?= $data['cellPhone'] ?>" maxlength="12" class="js-number-only" title="휴대폰번호를 입력해주세요!" placeholder="'-' 없이 입력하세요."/> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <div class="form-inline"> | |
| <span id="cellPhoneMsg" class="input_error_msg"></span> | |
| <label class="ncua-checkbox-field ncua-checkbox-field--xs has-text"> | |
| <span class="ncua-checkbox-input ncua-checkbox-input--xs ncua-checkbox-field__input"> | |
| <input type="checkbox" <?= ($mode === 'register') ? 'disabled' : '' ?> name="smsFl" value="y" <?= $checked['smsFl']['y']; ?>> | |
| </span> | |
| <span class="ncua-checkbox-field__text">마케팅 모바일 메시지 수신 동의</span> | |
| </label> | |
| </div> | |
| <p class="ncua-caution-text">수신동의설정 안내메일의 자동발송여부에 따라 회원정보의 수신동의설정 변경 시 해당 회원에게 SMS가 자동 발송됩니다.</p> | |
| <?php } ?> | |
| </div> | |
| </td> | |
| </tr> | |
| <!-- 휴대폰번호 수신/거부 --> | |
| <tr> | |
| <th><div data-tooltip-seq="014">휴대폰번호 수신동의/거부일</div></th> | |
| <td><div> | |
| <?php | |
| $smsLastReceiveAgreementDt = gd_isset($data['lastReceiveAgreementDt']['sms'], $data['entryDt']); | |
| $smsAgreementView = '동의 : ' . $smsLastReceiveAgreementDt; | |
| if (gd_isset($data['lastNotificationDt']['sms'], '-') != '-') { | |
| $smsAgreementView .= '<br/>(수신동의여부 확인SMS 발송<br/> : ' . $data['lastNotificationDt']['sms'] . ')'; | |
| } | |
| ?> | |
| <?= $data['smsFl'] == 'y' ? $smsAgreementView : '거부 : ' . $smsLastReceiveAgreementDt; ?> | |
| </div></td> | |
| </tr> | |
| <!-- 주소 --> | |
| <tr> | |
| <th><div data-tooltip-seq="015">주소</div></th> | |
| <td> | |
| <div class="ncua-flex-column ncua-align-items-start"> | |
| <?php if ($data['mallSno'] == $gGlobal['defaultMallSno'] || $mode == 'register') { ?> | |
| <!-- addr 1 --> | |
| <div class="ncua-member-addr"> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr1"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input readonly type="text" size="6" maxlength="5" name="zonecode" class="js-number" data-number="5" value="<?= $data['zonecode'] ?>" title="우편번호를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| <input type="hidden" name="zipcode" value="<?= $data['zipcode'] ?>"/> | |
| <span id="zipcodeText" class="number <?php if (strlen($data['zipcode']) != 7) { | |
| echo 'display-none'; | |
| } ?>">(<?php echo $data['zipcode']; ?>) | |
| </span> | |
| <input type="button" | |
| onclick="postcode_search('zonecode', 'address', 'zipcode');" | |
| value="주소찾기" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray"/> | |
| <!-- addr 2 --> | |
| <div class="ncua-input ncua-input--xs is-disabled ncua-member-addr2"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input readonly type="text" name="address" id="address" value="<?= $data['address']; ?>" title="주소를 입력해주세요!"/> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="ncua-input ncua-input--xs ncua-member-addr3"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="addressSub" id="addressSub" value="<?= $data['addressSub']; ?>" placeholder="상세주소를 입력하세요."/> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- <div class="ncua-flex ncua-flex-column ncua-gap-4"> | |
| </div> --> | |
| <?php } ?> | |
| </div> | |
| </td> | |
| </tr> | |
| <!-- 전화번호 --> | |
| <tr> | |
| <th><div data-tooltip-seq="016">전화번호</div></th> | |
| <td><div> | |
| <div class="form-inline"> | |
| <?php | |
| $phoneCallPrefixAttributes = [ | |
| 'id' => 'phoneCountryCode', | |
| 'name' => 'phoneCountryCode', | |
| ]; | |
| if ($mode != 'register' && $data['mallSno'] != $gGlobal['defaultMallSno']) { | |
| gd_select_box_by_call_prefix($phoneCallPrefixAttributes, $data['phoneCountryCode']); | |
| } | |
| ?> | |
| <div class="ncua-input ncua-input--xs ncua-input-width-150"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input type="text" name="phone" value="<?= $data['phone'] ?>" maxlength="12" class="js-number-only" placeholder="'-' 없이 입력하세요."/> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div></td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
변경 전base_agreement_with_private.php
| <?= $privateApprovalTableOption ?> | |
| <?= $privateConsignTable ?> | |
| <?= $privateOfferTable ?> | |
| <div class="table-title gd-help-manual mgt10"> | |
| 비회원 대상 동의항목 설정 | |
| </div> | |
| $(document).ready(function () { | |
| var $formSetup = $('#formSetup'); | |
| $.validator.addMethod("year", function (value) { | |
| var valid = moment(value, 'YYYY', true).isValid(); | |
| var checked = $('#agreementModeFlY').prop('checked'); | |
변경 후base_agreement_with_private.php
| <?= $privateApprovalTableOption ?> | |
| <?= $privateConsignTable ?> | |
| <?= $privateOfferTable ?> | |
| <?php if (!empty($privateMarketingMember)): ?> | |
| <table class="table table-cols"> | |
| <caption> | |
| [선택] 마케팅 목적 개인정보 수집 및 이용 동의 | |
| </caption> | |
| <colgroup> | |
| <col class="width-md"/> | |
| <col/> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>사용여부</th> | |
| <td> | |
| <label class="radio-inline" for="privateMarketingMemberFlY"> | |
| <input id="privateMarketingMemberFlY" type="radio" name="privateMarketingMemberFl" value="y" <?= $privateMarketingMember['modeFl'] == 'y' ? 'checked=checked' : ''; ?> /> | |
| 사용 | |
| </label> | |
| <label class="radio-inline" for="privateMarketingMemberFlN"> | |
| <input id="privateMarketingMemberFlN" type="radio" name="privateMarketingMemberFl" value="n" <?= $privateMarketingMember['modeFl'] != 'y' ? 'checked=checked' : ''; ?> /> | |
| 사용하지 않음 | |
| </label> | |
| <p class="notice notice-info js-marketing-use-notice">광고성 메시지를 보내려면 아래에 있는 [선택] 광고성 수신 동의 약관도 반드시 함께 사용해야 합니다.</p> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>안내 팝업 노출 여부</th> | |
| <td> | |
| <label class="radio-inline" for="privateMarketingMemberNoticePopupFlY"> | |
| <input id="privateMarketingMemberNoticePopupFlY" type="radio" name="privateMarketingMemberNoticePopupFl" value="y" <?= $privateMarketingMember['noticePopupFl'] == 'y' ? 'checked=checked' : ''; ?> /> | |
| 사용 | |
| </label> | |
| <label class="radio-inline" for="privateMarketingMemberNoticePopupFlN"> | |
| <input id="privateMarketingMemberNoticePopupFlN" type="radio" name="privateMarketingMemberNoticePopupFl" value="n" <?= $privateMarketingMember['noticePopupFl'] != 'y' ? 'checked=checked' : ''; ?> /> | |
| 사용하지 않음 | |
| </label> | |
| <p class="notice notice-info">안내 팝업 노출 여부를 ‘사용’으로 설정 시, 마케팅 목적의 개인정보 수집 및 이용 동의 이력이 없는 회원이 로그인 시 최초 1회에 한하여 팝업 안내가 출력됩니다.</p> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>내용입력</th> | |
| <td> | |
| <input type="text" class="form-control" id="privateMarketingMemberWriteTitle" name="privateMarketingMemberWriteTitle" value="<?= gd_htmlspecialchars($privateMarketingMember['informNm']) ?>"> | |
| <textarea id="privateMarketingMemberWriteWrite" name="privateMarketingMemberWriteWrite" rows="12" class="form-control mgt5"><?= gd_htmlspecialchars($privateMarketingMember['content']) ?></textarea> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <?php endif; ?> | |
| <?php if (!empty($advertisingReceive)): ?> | |
| <table class="table table-cols"> | |
| <caption> | |
| [선택] 광고성 수신 동의 | |
| </caption> | |
| <colgroup> | |
| <col class="width-md"/> | |
| <col/> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>사용여부</th> | |
| <td> | |
| <label class="checkbox-inline" for="advertisingReceiveMailFl"> | |
| <input id="advertisingReceiveMailFl" type="checkbox" name="advertisingReceiveMailFl" value="y" <?= $advertisingReceiveMailUse == 'y' ? 'checked="checked"' : '' ?> <?= $joinItemEmailUse == 'y' ? '' : 'disabled="disabled"' ?> /> | |
| 이메일 수신 동의 | |
| </label> | |
| <label class="checkbox-inline" for="advertisingReceiveSmsFl"> | |
| <input id="advertisingReceiveSmsFl" type="checkbox" name="advertisingReceiveSmsFl" value="y" <?= $advertisingReceiveSmsUse == 'y' ? 'checked="checked"' : '' ?> <?= $joinItemCellPhoneUse == 'y' ? '' : 'disabled="disabled"' ?> /> | |
| 모바일 메시지 수신 동의 | |
| </label> | |
| <?php if ($joinItemEmailUse != 'y' || $joinItemCellPhoneUse != 'y'): ?> | |
| <p class="notice notice-info">광고성 수신 동의는 회원가입 항목에서 이메일/휴대폰번호를 사용 중일 때만 설정 가능합니다.</p> | |
| <?php endif; ?> | |
| <p class="mgt5"> | |
| 이메일 : <?php if ($joinItemEmailUse == 'y'): ?>사용 | |
| <?php else: ?>사용 안 함 <a href="../member/member_joinitem.php" class="btn-link-underline" target="_blank">설정 바로가기></a><?php endif; ?><br/> | |
| 휴대폰번호 : <?php if ($joinItemCellPhoneUse == 'y'): ?>사용<?php else: ?>사용 안 함 <a href="../member/member_joinitem.php" class="btn-link-underline" target="_blank">설정 바로가기></a><?php endif; ?> | |
| </p> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>내용입력</th> | |
| <td> | |
| <input type="text" class="form-control" id="advertisingReceiveWriteTitle" name="advertisingReceiveWriteTitle" value="<?= gd_htmlspecialchars($advertisingReceive['informNm']) ?>"> | |
| <textarea id="advertisingReceiveWriteWrite" name="advertisingReceiveWriteWrite" rows="12" class="form-control mgt5"><?= gd_htmlspecialchars($advertisingReceive['content']) ?></textarea> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <?php endif; ?> | |
| <div class="table-title gd-help-manual mgt10"> | |
| 비회원 대상 동의항목 설정 | |
| </div> | |
| $(document).ready(function () { | |
| var $formSetup = $('#formSetup'); | |
| // 안내 팝업 노출 여부 비활성화 + 광고성 수신 동의 관련 안내 문구 숨김 | |
| const toggleMarketingNoticePopup = function () { | |
| const isUse = $('input[name=privateMarketingMemberFl]:checked').val() === 'y'; | |
| $('input[name=privateMarketingMemberNoticePopupFl]').prop('disabled', !isUse); | |
| $('.js-marketing-use-notice').toggle(isUse); | |
| }; | |
| $formSetup.on('change', 'input[name=privateMarketingMemberFl]', toggleMarketingNoticePopup); | |
| toggleMarketingNoticePopup(); | |
| $.validator.addMethod("year", function (value) { | |
| var valid = moment(value, 'YYYY', true).isValid(); | |
| var checked = $('#agreementModeFlY').prop('checked'); | |
변경 전member_crm_detail.php
| $checkBoxRow = 6; | |
| } | |
| ?> | |
| <form id="frm" action="../member/member_ps.php" method="post"> | |
| <input type="hidden" name="mode" id="mode" value="<?= $mode ?>"/> | |
| <input type="hidden" name="memNo" id="memNo" value="<?= $data['memNo'] ?>"/> | |
| <?php include gd_admin_skin_path("member/_member_view.php"); ?> | |
| <?php include "/../member/_member_view_history.php"; ?> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script type="text/javascript"> | |
| $('#emailDomain').removeClass('error'); | |
| $('#nickNm').removeClass('error'); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
변경 후member_crm_detail.php
| $checkBoxRow = 6; | |
| } | |
| ?> | |
| <link rel="stylesheet" href="<?= PATH_ADMIN_GD_SHARE ?>ncds/css/member/member-view.css"> | |
| <form id="frm" class="ncua-content" action="../member/member_ps.php" method="post"> | |
| <input type="hidden" name="mode" id="mode" value="<?= $mode ?>"/> | |
| <input type="hidden" name="memNo" id="memNo" value="<?= $data['memNo'] ?>"/> | |
| <?php include gd_admin_skin_path("member/_member_view.php"); ?> | |
| <?php include "/../member/_member_view_history.php"; ?> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member.js"></script> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/member2.js"></script> | |
| <script defer src="<?=gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/charcount.js')?>"></script> | |
| <script type="text/javascript"> | |
| $('#emailDomain').removeClass('error'); | |
| $('#nickNm').removeClass('error'); | |
| var certificationMaxFileSize = <?= $certificationMaxFileSize ?>; | |
| var join_field = <?= json_encode($joinField) ?>; | |
| </script> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| const memberPwManager = createCharCountManager({ | |
| targetClasses: ['js-member-pw'], | |
| }); | |
| memberPwManager.init(); | |
| const reMemberPwManager = createCharCountManager({ | |
| targetClasses: ['js-re-member-pw'], | |
| }); | |
| reMemberPwManager.init(); | |
| }); | |
| </script> | |
변경 전BuyerInformCode.php
| const PRIVATE_MEMBER_AUTO_APPROVAL_CONSENT = '991013'; | |
| /** 마케팅 활용을 위한 개인정보 수집 · 이용 동의 (비회원 주문 시) */ | |
| const PRIVATE_MARKETING = '001011'; | |
| /** 이용안내 */ | |
| const BASE_GUIDE = '006001'; | |
| /** 탈퇴안내 */ | |
| case self::PRIVATE_MARKETING: | |
| $this->initPrivateMarketing(); | |
| break; | |
| } | |
| } | |
| $this->_groupCd = '001'; | |
| } | |
| /** | |
| * 멤버 변수를 배열로 반환하는 함수 | |
| * | |
변경 후BuyerInformCode.php
| const PRIVATE_MEMBER_AUTO_APPROVAL_CONSENT = '991013'; | |
| /** 마케팅 활용을 위한 개인정보 수집 · 이용 동의 (비회원 주문 시) */ | |
| const PRIVATE_MARKETING = '001011'; | |
| /** 마케팅 목적 개인정보 수집 및 이용 동의 */ | |
| const PRIVATE_MARKETING_MEMBER = '001015'; | |
| /** 광고성 수신 동의 */ | |
| const ADVERTISING_RECEIVE = '001016'; | |
| /** 이용안내 */ | |
| const BASE_GUIDE = '006001'; | |
| /** 탈퇴안내 */ | |
| case self::PRIVATE_MARKETING: | |
| $this->initPrivateMarketing(); | |
| break; | |
| case self::PRIVATE_MARKETING_MEMBER: | |
| $this->initPrivateMarketingMember(); | |
| break; | |
| case self::ADVERTISING_RECEIVE: | |
| $this->initAdvertisingReceive(); | |
| break; | |
| } | |
| } | |
| $this->_groupCd = '001'; | |
| } | |
| /** | |
| * 멤버 변수에 마케팅 목적 개인정보 수집 및 이용 동의 관련 데이터베이스 조회 데이터 설정 | |
| * | |
| * @return void | |
| */ | |
| public function initPrivateMarketingMember() | |
| { | |
| $this->_informCd = self::PRIVATE_MARKETING_MEMBER; | |
| $this->_informNm = __('마케팅 목적 개인정보 수집 및 이용 동의'); | |
| $this->_groupCd = '001'; | |
| } | |
| /** | |
| * 멤버 변수에 광고성 수신 동의 관련 데이터베이스 조회 데이터 설정 | |
| * | |
| * @return void | |
| */ | |
| public function initAdvertisingReceive(): void | |
| { | |
| $this->_informCd = self::ADVERTISING_RECEIVE; | |
| $this->_informNm = __('광고성 수신 동의'); | |
| $this->_groupCd = '001'; | |
| } | |
| /** | |
| * 멤버 변수를 배열로 반환하는 함수 | |
| * | |
변경 전BuyerInform.php
| return $inform; | |
| } | |
| /** | |
| * 사용자 정의 이용약관 데이터 반환 함수 | |
| * | |
| if (empty($vo->getInformNm())) { | |
| $excludeField .= ',informNm'; | |
| } | |
| // 테이블명 반환 | |
| $tableName = $this->mall->getTableName(DB_BUYER_INFORM, $this->saveMallSno); | |
| $this->db->set_insert_db($tableName, $arrBind['param'], $arrBind['bind'], 'y'); | |
| } | |
| /** | |
| * 기본정책 약관, 개인정보관련 동의사항, 이용, 탈퇴 안내 저장 함수 | |
| * | |
| $vo->setModeFl(gd_isset($postValue['privateMarketingFl'], 'n')); | |
| } | |
| $strSQL = "SELECT sno, displayShopFl FROM " . $tableName . " WHERE informCd='" . $code . "'"; | |
| if ($mallSno > DEFAULT_MALL_NUMBER) { | |
| $strSQL .= " AND mallSno='" . $mallSno . "'"; | |
변경 후BuyerInform.php
| return $inform; | |
| } | |
| /** | |
| * 광고성 수신 동의 정보 반환 - 단일 배열 (상점명 치환코드 {rc_mallNm} 적용) | |
| * | |
| * @param int $mallSno | |
| * | |
| * @return array | |
| * @throws Exception | |
| */ | |
| public function getAdvertisingReceiveContentWithReplaceCode(int $mallSno = DEFAULT_MALL_NUMBER): array | |
| { | |
| /** @var \Bundle\Component\Design\ReplaceCode $replaceCode */ | |
| $replaceCode = App::load('\\Component\\Design\\ReplaceCode'); | |
| $replaceCode->initWithUnsetDiff( | |
| [ | |
| '{rc_mallNm}', | |
| ] | |
| ); | |
| $mallInfo = array_map(function ($value) { | |
| return $value['val']; | |
| }, $replaceCode->getDefinedCode()); | |
| $inform = $this->getInformData(BuyerInformCode::ADVERTISING_RECEIVE, $mallSno); | |
| if (!empty($inform['content'])) { | |
| $inform['content'] = str_replace(array_keys($mallInfo), array_values($mallInfo), $inform['content']); | |
| } | |
| return $inform; | |
| } | |
| /** | |
| * 사용자 정의 이용약관 데이터 반환 함수 | |
| * | |
| if (empty($vo->getInformNm())) { | |
| $excludeField .= ',informNm'; | |
| } | |
| // [선택] 마케팅 목적 개인정보 수집 및 이용 동의 / 광고성 수신 동의는 본문을 공백으로 저장하면 기존 내용 유지 | |
| if (in_array($vo->getInformCd(), [BuyerInformCode::PRIVATE_MARKETING_MEMBER, BuyerInformCode::ADVERTISING_RECEIVE], true) && empty($vo->getContent())) { | |
| $excludeField .= ',content'; | |
| } | |
| // 테이블명 반환 | |
| $tableName = $this->mall->getTableName(DB_BUYER_INFORM, $this->saveMallSno); | |
| $this->db->set_insert_db($tableName, $arrBind['param'], $arrBind['bind'], 'y'); | |
| } | |
| /** | |
| * 광고성 수신 동의 채널(이메일/모바일) 저장값 확정. | |
| * 가입항목(joinitem) 미사용 채널은 체크박스가 disabled 로 출력되어 POST 에 실리지 않으므로 이전 es_config 값을 보존한다. | |
| * es_config(member.advertisingReceive) 저장과 es_buyerInform modeFl 파생이 동일 결과를 쓰도록 단일화한다. | |
| * | |
| * @param array $post 저장 요청 POST 배열 (advertisingReceiveMailFl / advertisingReceiveSmsFl 포함 가능) | |
| * @param int $mallSno | |
| * | |
| * @return array ['email' => ['use' => 'y'|'n'], 'mobile' => ['use' => 'y'|'n']] | |
| */ | |
| public function resolveAdvertisingReceiveChannels(array $post, int $mallSno = DEFAULT_MALL_NUMBER): array | |
| { | |
| $joinItem = gd_policy('member.joinitem', $mallSno); | |
| $prevAdvertisingReceive = gd_policy('member.advertisingReceive', $mallSno); | |
| return [ | |
| 'email' => ['use' => ($joinItem['email']['use'] ?? 'n') === 'y' | |
| ? gd_isset($post['advertisingReceiveMailFl'], 'n') | |
| : ($prevAdvertisingReceive['email']['use'] ?? 'n')], | |
| 'mobile' => ['use' => ($joinItem['cellPhone']['use'] ?? 'n') === 'y' | |
| ? gd_isset($post['advertisingReceiveSmsFl'], 'n') | |
| : ($prevAdvertisingReceive['mobile']['use'] ?? 'n')], | |
| ]; | |
| } | |
| /** | |
| * 광고성 수신 동의 채널(이메일/모바일)의 프론트 노출 여부. | |
| * 노출 조건 = 가입항목(joinitem) 사용 AND 광고성 수신 동의(es_config) 사용. (가입항목 선검사 강제 → 호출부 누락 방지) | |
| * | |
| * @param int $mallSno | |
| * | |
| * @return array ['mail' => 'y'|'n', 'sms' => 'y'|'n'] | |
| */ | |
| public function getAdvertisingReceiveChannelUse(int $mallSno = DEFAULT_MALL_NUMBER): array | |
| { | |
| $joinItem = gd_policy('member.joinitem', $mallSno); | |
| $advertisingReceive = gd_policy('member.advertisingReceive', $mallSno); | |
| return [ | |
| 'mail' => (($joinItem['email']['use'] ?? 'n') === 'y' && ($advertisingReceive['email']['use'] ?? 'n') === 'y') ? 'y' : 'n', | |
| 'sms' => (($joinItem['cellPhone']['use'] ?? 'n') === 'y' && ($advertisingReceive['mobile']['use'] ?? 'n') === 'y') ? 'y' : 'n', | |
| ]; | |
| } | |
| /** | |
| * 광고성 수신 동의 사용 여부. 채널(이메일/모바일) 중 하나라도 노출 가능하면 사용(true), 둘 다 미사용이면 false. | |
| * es_buyerInform modeFl 대신 이 값을 프론트 노출/사용 판정 기준으로 쓴다. | |
| * | |
| * @param int $mallSno | |
| * | |
| * @return bool | |
| */ | |
| public function isUseAdvertisingReceive(int $mallSno = DEFAULT_MALL_NUMBER): bool | |
| { | |
| $channelUse = $this->getAdvertisingReceiveChannelUse($mallSno); | |
| return $channelUse['mail'] === 'y' || $channelUse['sms'] === 'y'; | |
| } | |
| /** | |
| * 기본정책 약관, 개인정보관련 동의사항, 이용, 탈퇴 안내 저장 함수 | |
| * | |
| $vo->setModeFl(gd_isset($postValue['privateMarketingFl'], 'n')); | |
| } | |
| if ($code == BuyerInformCode::PRIVATE_MARKETING_MEMBER) { | |
| $vo->setInformNm(strip_tags($postValue['privateMarketingMemberWriteTitle'])); | |
| $vo->setModeFl(gd_isset($postValue['privateMarketingMemberFl'], 'n')); | |
| $vo->setNoticePopupFl(gd_isset($postValue['privateMarketingMemberNoticePopupFl'], 'n')); | |
| } | |
| if ($code == BuyerInformCode::ADVERTISING_RECEIVE) { | |
| $advertisingReceiveChannels = $this->resolveAdvertisingReceiveChannels($postValue, (int)$mallSno); | |
| $vo->setInformNm(strip_tags($postValue['advertisingReceiveWriteTitle'])); | |
| $vo->setModeFl(($advertisingReceiveChannels['email']['use'] === 'y' || $advertisingReceiveChannels['mobile']['use'] === 'y') ? 'y' : 'n'); | |
| } | |
| $strSQL = "SELECT sno, displayShopFl FROM " . $tableName . " WHERE informCd='" . $code . "'"; | |
| if ($mallSno > DEFAULT_MALL_NUMBER) { | |
| $strSQL .= " AND mallSno='" . $mallSno . "'"; | |
변경 전BuyerInformVo.php
| private $regDt; | |
| private $modDt; | |
| private $displayShopFl; | |
| function __construct($code = null) | |
| { | |
| $this->displayShopFl = $displayShopFl; | |
| } | |
| /** | |
| * object return array | |
| * | |
변경 후BuyerInformVo.php
| private $regDt; | |
| private $modDt; | |
| private $displayShopFl; | |
| private string $noticePopupFl = 'n'; | |
| function __construct($code = null) | |
| { | |
| $this->displayShopFl = $displayShopFl; | |
| } | |
| /** | |
| * @return string | |
| */ | |
| public function getNoticePopupFl(): string | |
| { | |
| return $this->noticePopupFl; | |
| } | |
| /** | |
| * @param string $noticePopupFl | |
| */ | |
| public function setNoticePopupFl(string $noticePopupFl) | |
| { | |
| $this->noticePopupFl = $noticePopupFl; | |
| } | |
| /** | |
| * object return array | |
| * | |
변경 전DBTableField.php
| ['val' => 'scmDisplayFl', 'typ' => 's', 'def' => 'n'], // 모드 사용여부 | |
| ['val' => 'content', 'typ' => 's', 'def' => null], // 내용 | |
| ['val' => 'displayShopFl', 'typ' => 's', 'def' => 'n'], // 약관 노출 여부 | |
| ]; | |
| // @formatter:on | |
변경 후DBTableField.php
| ['val' => 'scmDisplayFl', 'typ' => 's', 'def' => 'n'], // 모드 사용여부 | |
| ['val' => 'content', 'typ' => 's', 'def' => null], // 내용 | |
| ['val' => 'displayShopFl', 'typ' => 's', 'def' => 'n'], // 약관 노출 여부 | |
| ['val' => 'noticePopupFl', 'typ' => 's', 'def' => 'n'], // 마케팅 목적 개인정보 수집 동의 안내 팝업 노출 여부 | |
| ]; | |
| // @formatter:on | |
변경 전MemberTableField.php
| 'def' => null, | |
| ], | |
| // 개인정보동의 취급업무 위탁 | |
| [ | |
| 'val' => 'foreigner', | |
| 'typ' => 's', | |
변경 후MemberTableField.php
| 'def' => null, | |
| ], | |
| // 개인정보동의 취급업무 위탁 | |
| [ | |
| 'val' => 'privateMarketingConsentOptionFl', | |
| 'typ' => 's', | |
| 'def' => '', // 미응답(빈값) 상태 유지 - DB DEFAULT '' 와 동일 | |
| ], | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 | |
| [ | |
| 'val' => 'privateMarketingConsentNoticePopupDt', | |
| 'typ' => 's', | |
| 'def' => null, | |
| ], | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 안내 팝업 노출 일시 (NULL:미노출) | |
| [ | |
| 'val' => 'foreigner', | |
| 'typ' => 's', | |
변경 전ExcelMember.php
| 'dbName' => 'member', | |
| 'dbKey' => 'smsFl', | |
| 'excelKey' => 'sms_fl', | |
| 'text' => __('SMS수신동의'), | |
| 'sample' => 'y', | |
| 'comment' => sprintf('y:%s<br />n:%s', __('받음'), __('거부')), | |
| 'desc' => sprintf('y:%s, n:%s, %s', __('받음'), __('거부'), __('기본은 y(받음)입니다.')), | |
| 'comment' => sprintf('n:%s<br />y:%s', __('동의안함'), __('동의함')), | |
| 'desc' => sprintf('n:%s, y:%s, %s', __('동의안함'), __('동의함'), __('기본은 n(동의안함)입니다.')), | |
| ], | |
| [ | |
| 'dbName' => 'member', | |
| 'dbKey' => 'foreigner', | |
변경 후ExcelMember.php
| 'dbName' => 'member', | |
| 'dbKey' => 'smsFl', | |
| 'excelKey' => 'sms_fl', | |
| 'text' => __('모바일메시지수신동의'), | |
| 'sample' => 'y', | |
| 'comment' => sprintf('y:%s<br />n:%s', __('받음'), __('거부')), | |
| 'desc' => sprintf('y:%s, n:%s, %s', __('받음'), __('거부'), __('기본은 y(받음)입니다.')), | |
| 'comment' => sprintf('n:%s<br />y:%s', __('동의안함'), __('동의함')), | |
| 'desc' => sprintf('n:%s, y:%s, %s', __('동의안함'), __('동의함'), __('기본은 n(동의안함)입니다.')), | |
| ], | |
| [ | |
| 'dbName' => 'member', | |
| 'dbKey' => 'privateMarketingConsentOptionFl', | |
| 'excelKey' => 'private_marketing_consent_option_fl', | |
| 'text' => __('마케팅 목적 개인정보 수집 및 이용'), | |
| 'sample' => 'n', | |
| 'comment' => sprintf('n:%s<br />y:%s', __('동의안함'), __('동의함')), | |
| 'desc' => sprintf('n:%s, y:%s, %s', __('동의안함'), __('동의함'), __('기본은 n(동의안함)입니다.')), | |
| ], | |
| [ | |
| 'dbName' => 'member', | |
| 'dbKey' => 'foreigner', | |
변경 전History.php
| //__('마일리지') | |
| 'deposit' => '예치금', | |
| //__('예치금') | |
| 'maillingFl' => '메일수신동의', | |
| //__('메일수신동의') | |
| 'smsFl' => 'SMS수신동의', | |
| //__('SMS수신동의') | |
| 'marriFl' => '결혼여부', | |
| //__('결혼여부') | |
| 'marriDate' => '결혼기념일', | |
| //__('개인정보 수집 및 이용 필수') | |
| 'privateApprovalOptionFl' => '개인정보 수집 및 이용 선택', | |
| //__('개인정보 수집 및 이용 선택') | |
| 'privateOfferFl' => '개인정보동의 제3자 제공', | |
| //__('개인정보동의 제3자 제공') | |
| 'privateConsignFl' => '개인정보동의 취급업무 위탁', | |
| $different = []; | |
| $this->getDifferent($different); | |
| if (gd_array_key_exists('smsFl', $different)) { | |
| $this->filters[] = 'smsFl'; | |
| } | |
| if (gd_array_key_exists('maillingFl', $different)) { | |
| $this->filters[] = 'maillingFl'; | |
| } | |
| if (gd_array_key_exists('privateApprovalOptionFl', $different)) { | |
| $this->filters[] = 'privateApprovalOptionFl'; | |
| } | |
| if (gd_array_key_exists('privateOfferFl', $different)) { | |
| $this->filters[] = 'privateOfferFl'; | |
| } | |
| if (gd_array_key_exists('privateConsignFl', $different)) { | |
| $this->filters[] = 'privateConsignFl'; | |
| } | |
| if (key_exists('companyCertification', $different)) { | |
| } | |
| $beforeValue = $displayArray[$beforeValue]; | |
| $value = $displayArray[$value]; | |
| if (gd_array_key_exists('groupModDt', $this->after) && ($this->before['groupModDt'] != $this->after['groupModDt'])) { | |
| $different['groupModDt'] = [ | |
| $this->before['groupModDt'], | |
| $this->after['groupModDt'], | |
| $beforeValue = $displayArray[$beforeValue]; | |
| $value = $displayArray[$value]; | |
| } | |
| unset($displayArray); | |
| $different[$key] = [ | |
| $beforeValue, | |
| StringUtils::strIsSet($item['otherValue'], '{}'); | |
| $otherValue = json_decode($item['otherValue'], true); | |
| StringUtils::strIsSet($otherValue['smsFl']['sms080']['regDt'], ''); | |
| if (!empty($otherValue['smsFl']['sms080']['regDt']) && $item['updateColumn'] == 'SMS수신동의') { | |
| $item['displayOtherValue'] = sprintf(' (080 수신거부 : %s)', $otherValue['smsFl']['sms080']['regDt']); | |
| } | |
| if (!empty($otherValue['reflectApplyMemberInfo']['orderNo']) && empty($otherValue['simpleJoin'])) { | |
| */ | |
| public function selectLastReceiveAgreementByMember($memberNo) | |
| { | |
| // __('SMS수신동의') | |
| // __('메일수신동의') | |
| $this->db->strField = 'mh.memNo, mh.updateColumn, mh.afterValue, MAX(mh.regDt) AS lastUpdateDt'; | |
| $this->db->strWhere = 'mh.memNo=? AND mh.updateColumn IN (\'SMS수신동의\', \'메일수신동의\')'; | |
| $this->db->strGroup = 'mh.updateColumn'; | |
| $this->db->bind_param_push($bind, 'i', $memberNo); | |
| $query = $this->db->query_complete(); | |
| */ | |
| public function getLastReceiveAgreementByMember($memberNo) | |
| { | |
| // __('SMS수신동의') | |
| // __('메일수신동의') | |
| $history = $this->selectLastReceiveAgreementByMember($memberNo); | |
| $result = []; | |
| foreach ($history as $item) { | |
| if ($item['updateColumn'] == 'SMS수신동의') { | |
| $result['lastReceiveAgreementDt']['sms'] = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| } elseif ($item['updateColumn'] == '메일수신동의') { | |
| $result['lastReceiveAgreementDt']['mail'] = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| } | |
| } | |
| return $result; | |
| $resultArray =[]; | |
| $this->db->strField = 'mh.memNo, mh.updateColumn, MAX(mh.regDt) AS lastUpdateDt'; | |
| $this->db->strWhere = 'mh.memNo in ('.gd_implode(',', $memberNos).') AND mh.updateColumn IN (\'SMS수신동의\', \'메일수신동의\')'; | |
| $this->db->strGroup = 'mh.memNo, mh.updateColumn'; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MEMBER_HISTORY . ' AS mh' . gd_implode(' ', $query); | |
| if (is_array($memberNos)) { | |
| $history = $this->selectLastReceiveAgreementByMembers($memberNos); | |
| foreach ($history as $item) { | |
| if ($item['updateColumn'] == 'SMS수신동의') { | |
| $result[$item['memNo']]['lastReceiveAgreementDt']['sms'] = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| } elseif ($item['updateColumn'] == '메일수신동의') { | |
| $result[$item['memNo']]['lastReceiveAgreementDt']['mail'] = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| } | |
| } | |
| } | |
변경 후History.php
| //__('마일리지') | |
| 'deposit' => '예치금', | |
| //__('예치금') | |
| 'maillingFl' => '이메일 수신 동의', | |
| //__('이메일 수신 동의') | |
| 'smsFl' => '모바일 메시지 수신 동의', | |
| //__('모바일 메시지 수신 동의') | |
| 'marriFl' => '결혼여부', | |
| //__('결혼여부') | |
| 'marriDate' => '결혼기념일', | |
| //__('개인정보 수집 및 이용 필수') | |
| 'privateApprovalOptionFl' => '개인정보 수집 및 이용 선택', | |
| //__('개인정보 수집 및 이용 선택') | |
| 'privateMarketingConsentOptionFl' => '마케팅 목적 개인정보 수집 및 이용 동의', | |
| //__('마케팅 목적 개인정보 수집 및 이용 동의') | |
| 'privateOfferFl' => '개인정보동의 제3자 제공', | |
| //__('개인정보동의 제3자 제공') | |
| 'privateConsignFl' => '개인정보동의 취급업무 위탁', | |
| $different = []; | |
| $this->getDifferent($different); | |
| if (array_key_exists('smsFl', $different)) { | |
| $this->filters[] = 'smsFl'; | |
| } | |
| if (array_key_exists('maillingFl', $different)) { | |
| $this->filters[] = 'maillingFl'; | |
| } | |
| if (array_key_exists('privateApprovalFl', $different)) { | |
| $this->filters[] = 'privateApprovalFl'; | |
| } | |
| if (array_key_exists('privateApprovalOptionFl', $different)) { | |
| $this->filters[] = 'privateApprovalOptionFl'; | |
| } | |
| if (array_key_exists('privateMarketingConsentOptionFl', $different)) { | |
| $this->filters[] = 'privateMarketingConsentOptionFl'; | |
| } | |
| if (array_key_exists('privateOfferFl', $different)) { | |
| $this->filters[] = 'privateOfferFl'; | |
| } | |
| if (array_key_exists('privateConsignFl', $different)) { | |
| $this->filters[] = 'privateConsignFl'; | |
| } | |
| if (key_exists('companyCertification', $different)) { | |
| } | |
| $beforeValue = $displayArray[$beforeValue]; | |
| $value = $displayArray[$value]; | |
| if (array_key_exists('groupModDt', $this->after) && ($this->before['groupModDt'] != $this->after['groupModDt'])) { | |
| $different['groupModDt'] = [ | |
| $this->before['groupModDt'], | |
| $this->after['groupModDt'], | |
| $beforeValue = $displayArray[$beforeValue]; | |
| $value = $displayArray[$value]; | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의: 미응답(빈값)은 미동의(n)로 표시 (비교는 원본이라 최초 응답도 이력에 남음) | |
| if ('privateMarketingConsentOptionFl' == $key && '' === $beforeValue) { | |
| $beforeValue = 'n'; | |
| } | |
| unset($displayArray); | |
| $different[$key] = [ | |
| $beforeValue, | |
| StringUtils::strIsSet($item['otherValue'], '{}'); | |
| $otherValue = json_decode($item['otherValue'], true); | |
| StringUtils::strIsSet($otherValue['smsFl']['sms080']['regDt'], ''); | |
| // 'SMS수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| if (!empty($otherValue['smsFl']['sms080']['regDt']) && in_array($item['updateColumn'], ['모바일 메시지 수신 동의', 'SMS수신동의'], true)) { | |
| $item['displayOtherValue'] = sprintf(' (080 수신거부 : %s)', $otherValue['smsFl']['sms080']['regDt']); | |
| } | |
| if (!empty($otherValue['reflectApplyMemberInfo']['orderNo']) && empty($otherValue['simpleJoin'])) { | |
| */ | |
| public function selectLastReceiveAgreementByMember($memberNo) | |
| { | |
| // __('모바일 메시지 수신 동의') | |
| // __('이메일 수신 동의') | |
| // __('마케팅 목적 개인정보 수집 및 이용 동의') | |
| $this->db->strField = 'mh.memNo, mh.updateColumn, mh.afterValue, MAX(mh.regDt) AS lastUpdateDt'; | |
| // 'SMS수신동의'/'메일수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| $this->db->strWhere = 'mh.memNo=? AND mh.updateColumn IN (\'모바일 메시지 수신 동의\', \'SMS수신동의\', \'이메일 수신 동의\', \'메일수신동의\', \'마케팅 목적 개인정보 수집 및 이용 동의\')'; | |
| $this->db->strGroup = 'mh.updateColumn'; | |
| $this->db->bind_param_push($bind, 'i', $memberNo); | |
| $query = $this->db->query_complete(); | |
| */ | |
| public function getLastReceiveAgreementByMember($memberNo) | |
| { | |
| // __('모바일 메시지 수신 동의') | |
| // __('이메일 수신 동의') | |
| $history = $this->selectLastReceiveAgreementByMember($memberNo); | |
| $result = []; | |
| foreach ($history as $item) { | |
| $dt = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| // 'SMS수신동의'/'메일수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| if (in_array($item['updateColumn'], ['모바일 메시지 수신 동의', 'SMS수신동의'], true)) { | |
| $key = 'sms'; | |
| } elseif (in_array($item['updateColumn'], ['이메일 수신 동의', '메일수신동의'], true)) { | |
| $key = 'mail'; | |
| } elseif ($item['updateColumn'] == '마케팅 목적 개인정보 수집 및 이용 동의') { | |
| $key = 'privateMkt'; | |
| } else { | |
| continue; | |
| } | |
| // 옛/새 라벨이 각각 그룹으로 나뉘어 올 수 있어 더 늦은 일자만 유지 | |
| if (empty($result['lastReceiveAgreementDt'][$key]) || $result['lastReceiveAgreementDt'][$key] < $dt) { | |
| $result['lastReceiveAgreementDt'][$key] = $dt; | |
| } | |
| } | |
| return $result; | |
| } | |
| /** | |
| * 회원의 개인정보 동의 항목별 마지막 변경 일시 조회 (updateColumn 한글 라벨 그룹, MAX regDt) | |
| * | |
| * @param $memberNo | |
| * | |
| * @return array | |
| */ | |
| public function selectLastPrivateAgreementByMember($memberNo): array | |
| { | |
| // __('개인정보 수집 및 이용 필수') | |
| // __('개인정보 수집 및 이용 선택') | |
| // __('개인정보동의 제3자 제공') | |
| // __('개인정보동의 취급업무 위탁') | |
| // __('마케팅 목적 개인정보 수집 및 이용 동의') | |
| $this->db->strField = 'mh.updateColumn, MAX(mh.regDt) AS lastUpdateDt'; | |
| $this->db->strWhere = 'mh.memNo=? AND mh.updateColumn IN (\'개인정보 수집 및 이용 필수\', \'개인정보 수집 및 이용 선택\', \'개인정보동의 제3자 제공\', \'개인정보동의 취급업무 위탁\', \'마케팅 목적 개인정보 수집 및 이용 동의\')'; | |
| $this->db->strGroup = 'mh.updateColumn'; | |
| $this->db->bind_param_push($bind, 'i', $memberNo); | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MEMBER_HISTORY . ' AS mh' . implode(' ', $query); | |
| $result = $this->db->query_fetch($strSQL, $bind); | |
| return $result; | |
| } | |
| /** | |
| * 회원의 개인정보 동의 항목별 마지막 변경 일시 (컬럼명 => 'Y-m-d H:i:s') | |
| * 이력이 없는 항목은 키 자체가 없으므로 호출부에서 entryDt 등으로 폴백한다. | |
| * | |
| * @param int $memberNo | |
| * | |
| * @return array privateApprovalFl / privateApprovalOptionFl / privateOfferFl / privateConsignFl / privateMarketingConsentOptionFl 중 이력 있는 항목만 | |
| */ | |
| public function getLastPrivateAgreementDateByMember(int $memberNo): array | |
| { | |
| $labelToColumn = [ | |
| '개인정보 수집 및 이용 필수' => 'privateApprovalFl', | |
| '개인정보 수집 및 이용 선택' => 'privateApprovalOptionFl', | |
| '개인정보동의 제3자 제공' => 'privateOfferFl', | |
| '개인정보동의 취급업무 위탁' => 'privateConsignFl', | |
| '마케팅 목적 개인정보 수집 및 이용 동의' => 'privateMarketingConsentOptionFl', | |
| ]; | |
| $history = $this->selectLastPrivateAgreementByMember($memberNo); | |
| $result = []; | |
| foreach ($history as $item) { | |
| $column = $labelToColumn[$item['updateColumn']] ?? null; | |
| if ($column === null) { | |
| continue; | |
| } | |
| $result[$column] = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| } | |
| return $result; | |
| $resultArray =[]; | |
| $this->db->strField = 'mh.memNo, mh.updateColumn, MAX(mh.regDt) AS lastUpdateDt'; | |
| // 'SMS수신동의'/'메일수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| $this->db->strWhere = 'mh.memNo in ('.gd_implode(',', $memberNos).') AND mh.updateColumn IN (\'모바일 메시지 수신 동의\', \'SMS수신동의\', \'이메일 수신 동의\', \'메일수신동의\')'; | |
| $this->db->strGroup = 'mh.memNo, mh.updateColumn'; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MEMBER_HISTORY . ' AS mh' . gd_implode(' ', $query); | |
| if (is_array($memberNos)) { | |
| $history = $this->selectLastReceiveAgreementByMembers($memberNos); | |
| foreach ($history as $item) { | |
| $dt = DateTimeUtils::dateFormat('Y-m-d H:i:s', $item['lastUpdateDt']); | |
| // 'SMS수신동의'/'메일수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| if (in_array($item['updateColumn'], ['모바일 메시지 수신 동의', 'SMS수신동의'], true)) { | |
| $key = 'sms'; | |
| } elseif (in_array($item['updateColumn'], ['이메일 수신 동의', '메일수신동의'], true)) { | |
| $key = 'mail'; | |
| } else { | |
| continue; | |
| } | |
| // 옛/새 라벨이 각각 그룹으로 나뉘어 올 수 있어 더 늦은 일자만 유지 | |
| if (empty($result[$item['memNo']]['lastReceiveAgreementDt'][$key]) || $result[$item['memNo']]['lastReceiveAgreementDt'][$key] < $dt) { | |
| $result[$item['memNo']]['lastReceiveAgreementDt'][$key] = $dt; | |
| } | |
| } | |
| } | |
변경 전MemberAdmin.php
| } | |
| $this->db->strJoin = ' LEFT JOIN ' . DB_MEMBER_SNS . ' AS ms ON m.memNo = ms.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_GROUP . ' AS mg ON m.groupSno = mg.sno'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HISTORY . ' AS mh ON (m.memNo=mh.memNo AND mh.updateColumn=\'SMS수신동의\')'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HISTORY . ' AS mh2 ON (m.memNo=mh2.memNo AND mh2.updateColumn=\'메일수신동의\')'; | |
| $this->db->strGroup = 'm.memNo'; | |
| $arrQuery = $this->db->query_complete(true, true); | |
| $strSQL = 'SELECT ' . array_shift($arrQuery) . ' FROM ' . DB_MEMBER . ' AS m ' . gd_implode(' ', $arrQuery); | |
| } | |
| } | |
| $arrData = $this->validateMemberByAdminModification($arrData); | |
| foreach ($preservedFileKeys as $fileKey => $fileVal) { | |
| \App::getInstance('session')->set(SESSION_GLOBAL_MALL, ['isAdminModify' => true]); | |
| } | |
| \Component\Member\MemberValidation::addValidateMember($v, $require); | |
| $v->add('memNo', 'number', true); | |
| if (!$this->isExcelUpload) { | |
| if (gd_isset($params['memPw'], '') !== '') { | |
변경 후MemberAdmin.php
| } | |
| $this->db->strJoin = ' LEFT JOIN ' . DB_MEMBER_SNS . ' AS ms ON m.memNo = ms.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_GROUP . ' AS mg ON m.groupSno = mg.sno'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HISTORY . ' AS mh ON (m.memNo=mh.memNo AND mh.updateColumn=\'모바일 메시지 수신 동의\')'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HISTORY . ' AS mh2 ON (m.memNo=mh2.memNo AND mh2.updateColumn=\'이메일 수신 동의\')'; | |
| $this->db->strGroup = 'm.memNo'; | |
| $arrQuery = $this->db->query_complete(true, true); | |
| $strSQL = 'SELECT ' . array_shift($arrQuery) . ' FROM ' . DB_MEMBER . ' AS m ' . gd_implode(' ', $arrQuery); | |
| } | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의는 약관 사용 시에만 포함 | |
| $privateMarketingMemberData = (new \Component\Agreement\BuyerInform())->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_MARKETING_MEMBER); | |
| if (($privateMarketingMemberData[0]['modeFl'] ?? 'n') === 'y') { | |
| StringUtils::strIsSet($arrData['privateMarketingConsentOptionFl'], 'n'); | |
| } | |
| $arrData = $this->validateMemberByAdminModification($arrData); | |
| foreach ($preservedFileKeys as $fileKey => $fileVal) { | |
| \App::getInstance('session')->set(SESSION_GLOBAL_MALL, ['isAdminModify' => true]); | |
| } | |
| \Component\Member\MemberValidation::addValidateMember($v, $require); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 (validator 미등록 시 act garbageDelete 로 제거되어 미저장) | |
| $v->add('privateMarketingConsentOptionFl', 'yn', false, '{' . __('마케팅 목적 개인정보 수집 및 이용 동의') . '}'); | |
| $v->add('memNo', 'number', true); | |
| if (!$this->isExcelUpload) { | |
| if (gd_isset($params['memPw'], '') !== '') { | |
변경 전MemberDAO.php
| $this->db->strField = 'm.memNo, m.memId, m.memNm, m.groupSno, m.mileage, m.deposit, m.smsFl, m.maillingFl, m.cellPhone, m.email'; | |
| $this->db->strField .= ', ' . $strFieldBySmsAgreementDt . ', ' . $strFieldByMailAgreementDt; | |
| $this->db->strJoin = ' LEFT JOIN (SELECT memNo, COUNT(*) AS cnt, MAX(regDt) AS maxRegDt FROM ' . DB_MEMBER_HISTORY . ' WHERE updateColumn=\'SMS수신동의\' GROUP BY memNo) AS mh_sms ON m.memNo = mh_sms.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN (SELECT memNo, COUNT(*) AS cnt, MAX(regDt) AS maxRegDt FROM ' . DB_MEMBER_HISTORY . ' WHERE updateColumn=\'메일수신동의\' GROUP BY memNo) AS mh_mail ON m.memNo = mh_mail.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN (SELECT DISTINCT memNo FROM ' . DB_MEMBER_NOTIFICATION_LOG . ' WHERE ReasonCode=\'' . MailMimeAuto::AGREEMENT2YPERIOD . '\' AND regDt >= \'' . $standardDt . ' 00:00:00\' AND regDt <= \'' . $nowDt . ' 23:59:59\') AS mnl ON m.memNo = mnl.memNo'; | |
| $this->db->strWhere = ''; | |
| $this->db->bindParameter('sexFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('maillingFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('smsFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('calendarFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('marriFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('connectSns', $params, $arrBind, $arrWhere, 'tableMemberSns', 'ms', 'snsTypeFl'); | |
| $query = MemberModel::from('es_member as m') | |
| ->leftJoin('es_memberHistory as mh', function ($join) { | |
| $join->on('mh.memNo', '=', 'm.memNo') | |
| ->where('mh.updateColumn', 'SMS수신동의'); | |
| }) | |
| ->leftJoin('es_memberHistory as mh2', function ($join) { | |
| $join->on('mh2.memNo', '=', 'm.memNo') | |
| ->where('mh2.updateColumn', '메일수신동의'); | |
| }) | |
| ->leftJoin('es_memberGroup as mg', 'm.groupSno', '=', 'mg.sno'); | |
변경 후MemberDAO.php
| $this->db->strField = 'm.memNo, m.memId, m.memNm, m.groupSno, m.mileage, m.deposit, m.smsFl, m.maillingFl, m.cellPhone, m.email'; | |
| $this->db->strField .= ', ' . $strFieldBySmsAgreementDt . ', ' . $strFieldByMailAgreementDt; | |
| // 'SMS수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| $this->db->strJoin = ' LEFT JOIN (SELECT memNo, COUNT(*) AS cnt, MAX(regDt) AS maxRegDt FROM ' . DB_MEMBER_HISTORY . ' WHERE updateColumn IN (\'모바일 메시지 수신 동의\', \'SMS수신동의\') GROUP BY memNo) AS mh_sms ON m.memNo = mh_sms.memNo'; | |
| // '메일수신동의' 는 구 라벨 - 마이그레이션 미완 데이터 대비 | |
| $this->db->strJoin .= ' LEFT JOIN (SELECT memNo, COUNT(*) AS cnt, MAX(regDt) AS maxRegDt FROM ' . DB_MEMBER_HISTORY . ' WHERE updateColumn IN (\'이메일 수신 동의\', \'메일수신동의\') GROUP BY memNo) AS mh_mail ON m.memNo = mh_mail.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN (SELECT DISTINCT memNo FROM ' . DB_MEMBER_NOTIFICATION_LOG . ' WHERE ReasonCode=\'' . MailMimeAuto::AGREEMENT2YPERIOD . '\' AND regDt >= \'' . $standardDt . ' 00:00:00\' AND regDt <= \'' . $nowDt . ' 23:59:59\') AS mnl ON m.memNo = mnl.memNo'; | |
| $this->db->strWhere = ''; | |
| $this->db->bindParameter('sexFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('maillingFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('smsFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 검색값 화이트리스트 정규화 | |
| if (!in_array($params['privateMarketingConsentOptionFl'] ?? '', ['', 'y', 'n'], true)) { | |
| $params['privateMarketingConsentOptionFl'] = ''; | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 (미동의는 동의여부 저장 안 한 디폴트('') 포함이라 != 'y') | |
| if (!empty($params['privateMarketingConsentOptionFl'])) { | |
| $arrWhere[] = $params['privateMarketingConsentOptionFl'] === 'y' | |
| ? "m.privateMarketingConsentOptionFl = 'y'" | |
| : "m.privateMarketingConsentOptionFl != 'y'"; | |
| } | |
| $this->db->bindParameter('calendarFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('marriFl', $params, $arrBind, $arrWhere, 'tableMember', 'm'); | |
| $this->db->bindParameter('connectSns', $params, $arrBind, $arrWhere, 'tableMemberSns', 'ms', 'snsTypeFl'); | |
| $query = MemberModel::from('es_member as m') | |
| ->leftJoin('es_memberHistory as mh', function ($join) { | |
| // '모바일 메시지 수신 동의'(신규) / 'SMS수신동의'(구 라벨) dual-match - 마이그레이션 미완 데이터 대비 | |
| $join->on('mh.memNo', '=', 'm.memNo') | |
| ->whereIn('mh.updateColumn', ['모바일 메시지 수신 동의', 'SMS수신동의']); | |
| }) | |
| ->leftJoin('es_memberHistory as mh2', function ($join) { | |
| // '이메일 수신 동의'(신규) / '메일수신동의'(구 라벨) dual-match - 마이그레이션 미완 데이터 대비 | |
| $join->on('mh2.memNo', '=', 'm.memNo') | |
| ->whereIn('mh2.updateColumn', ['이메일 수신 동의', '메일수신동의']); | |
| }) | |
| ->leftJoin('es_memberGroup as mg', 'm.groupSno', '=', 'mg.sno'); | |
변경 전Member.php
| } | |
| } | |
| /** | |
| * 로그인 비밀번호를 재검증 하는 함수 | |
| * | |
| $v->add('privateApprovalOptionFl', '', false, '{' . __('개인정보 수집.이용 동의 선택사항') . '}'); // 개인정보동의 이용자 동의사항 | |
| $v->add('privateOfferFl', '', false, '{' . __('개인정보동의 제3자 제공') . '}'); // 개인정보동의 제3자 제공 | |
| $v->add('privateConsignFl', '', false, '{' . __('개인정보동의 취급업무 위탁') . '}'); // 개인정보동의 취급업무 위탁 | |
| $v->add('foreigner', '', false, '{' . __('내외국인구분') . '}'); // 내외국인구분 | |
| $v->add('dupeinfo', '', false, '{' . __('본인확인 중복가입확인정보') . '}'); // 본인확인 중복가입확인정보 | |
| $v->add('pakey', '', false, '{' . __('본인확인 번호') . '}'); // 본인확인 번호 | |
| $vo->setPrivateApprovalOptionFl(json_encode($joinSession->get('privateApprovalOptionFl'), JSON_UNESCAPED_SLASHES)); | |
| $vo->setPrivateOfferFl(json_encode($joinSession->get('privateOfferFl'), JSON_UNESCAPED_SLASHES)); | |
| $vo->setPrivateConsignFl(json_encode($joinSession->get('privateConsignFl'), JSON_UNESCAPED_SLASHES)); | |
| $vo->setForeigner($joinSession->get('foreigner')); | |
| $vo->setDupeinfo($joinSession->get('dupeinfo')); | |
| $vo->setPakey($joinSession->get('pakey')); | |
| 'sexFl', | |
| 'marriFl', | |
| 'expirationFl', | |
| ], $memberData | |
| ); | |
변경 후Member.php
| } | |
| } | |
| /** | |
| * 마케팅 목적 개인정보 수집 및 이용 동의 안내(alert) 노출 여부 판정 + 노출 이력 기록 | |
| * 조건 통과 시 노출 이력(privateMarketingConsentNoticePopupDt)에 노출시각을 기록해 계정당 1회만 노출 | |
| * | |
| * @return bool 안내 노출 대상이면 true (동시에 노출 이력 기록) | |
| * @throws Exception | |
| */ | |
| public function markPrivateMarketingConsentNoticeShown(): bool | |
| { | |
| if (!MemberUtil::isLogin()) { | |
| return false; | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 약관(001015) 사용중(modeFl='y') + 안내 팝업 노출 사용(noticePopupFl='y') | |
| /** @var \Bundle\Component\Agreement\BuyerInform $buyerInform */ | |
| $buyerInform = \App::load('\\Component\\Agreement\\BuyerInform'); | |
| $inform = $buyerInform->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_MARKETING_MEMBER, 'modeFl, noticePopupFl'); | |
| if (($inform[0]['modeFl'] ?? 'n') !== 'y' || ($inform[0]['noticePopupFl'] ?? 'n') !== 'y') { | |
| return false; | |
| } | |
| $member = MemberUtil::getMemberBySession('memNo, privateMarketingConsentOptionFl, privateMarketingConsentNoticePopupDt'); | |
| $noticeDt = $member['privateMarketingConsentNoticePopupDt'] ?? ''; | |
| $alreadyNoticed = !empty($noticeDt) && $noticeDt !== '0000-00-00 00:00:00'; | |
| // 동의('y'), 안내 노출 이력이 있으면 미노출 | |
| if (($member['privateMarketingConsentOptionFl'] ?? '') === 'y' || $alreadyNoticed) { | |
| return false; | |
| } | |
| // 노출 이력 기록 (계정당 평생 1회 — 노출했다는 사실만 저장, 동의/거부와 무관) | |
| try { | |
| $this->update($member['memNo'], 'memNo', ['privateMarketingConsentNoticePopupDt'], [DateTimeUtils::dateFormat('Y-m-d H:i:s', 'now')]); | |
| } catch (\Exception $e) { | |
| \Logger::channel('userLogin')->warning('마케팅 목적 개인정보 수집 및 이용 동의 안내 노출 이력 기록 실패', ['memNo' => $member['memNo'], 'exception' => $e]); | |
| return false; | |
| } | |
| return true; | |
| } | |
| /** | |
| * 로그인 비밀번호를 재검증 하는 함수 | |
| * | |
| $v->add('privateApprovalOptionFl', '', false, '{' . __('개인정보 수집.이용 동의 선택사항') . '}'); // 개인정보동의 이용자 동의사항 | |
| $v->add('privateOfferFl', '', false, '{' . __('개인정보동의 제3자 제공') . '}'); // 개인정보동의 제3자 제공 | |
| $v->add('privateConsignFl', '', false, '{' . __('개인정보동의 취급업무 위탁') . '}'); // 개인정보동의 취급업무 위탁 | |
| $v->add('privateMarketingConsentOptionFl', 'yn', false, '{' . __('마케팅 목적 개인정보 수집 및 이용 동의') . '}'); // 마케팅 목적 개인정보 수집 및 이용 동의 | |
| $v->add('maillingFl', 'yn', false, '{' . __('이메일 수신 동의') . '}'); // 광고성 수신 동의 - 이메일 | |
| $v->add('smsFl', 'yn', false, '{' . __('모바일 메시지 수신 동의') . '}'); // 광고성 수신 동의 - 모바일 | |
| $v->add('foreigner', '', false, '{' . __('내외국인구분') . '}'); // 내외국인구분 | |
| $v->add('dupeinfo', '', false, '{' . __('본인확인 중복가입확인정보') . '}'); // 본인확인 중복가입확인정보 | |
| $v->add('pakey', '', false, '{' . __('본인확인 번호') . '}'); // 본인확인 번호 | |
| $vo->setPrivateApprovalOptionFl(json_encode($joinSession->get('privateApprovalOptionFl'), JSON_UNESCAPED_SLASHES)); | |
| $vo->setPrivateOfferFl(json_encode($joinSession->get('privateOfferFl'), JSON_UNESCAPED_SLASHES)); | |
| $vo->setPrivateConsignFl(json_encode($joinSession->get('privateConsignFl'), JSON_UNESCAPED_SLASHES)); | |
| // 마수동 약관 사용중(modeFl='y')일 때만 동의('y')/미동의('n') 확정. 미사용 시 ''(미응답) = 로그인 안내 팝업 대상. | |
| $privateMarketingConsentOptionFl = $joinSession->get('privateMarketingConsentOptionFl'); | |
| $buyerInform = \App::load('\\Component\\Agreement\\BuyerInform'); | |
| $privateMarketingMember = $buyerInform->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_MARKETING_MEMBER, 'modeFl'); | |
| if (($privateMarketingMember[0]['modeFl'] ?? 'n') === 'y') { | |
| $privateMarketingConsentOptionFl = ($privateMarketingConsentOptionFl === 'y') ? 'y' : 'n'; | |
| // 약관 사용 중 가입 = 이미 선택함 → 로그인 안내 팝업 제외 (노출 이력에 가입 시각 기록) | |
| $vo->setPrivateMarketingConsentNoticePopupDt(date('Y-m-d H:i:s')); | |
| } else { | |
| $privateMarketingConsentOptionFl = ''; | |
| } | |
| $vo->setPrivateMarketingConsentOptionFl($privateMarketingConsentOptionFl); | |
| $vo->setMaillingFl($joinSession->get('maillingFl')); | |
| $vo->setSmsFl($joinSession->get('smsFl')); | |
| $vo->setForeigner($joinSession->get('foreigner')); | |
| $vo->setDupeinfo($joinSession->get('dupeinfo')); | |
| $vo->setPakey($joinSession->get('pakey')); | |
| 'sexFl', | |
| 'marriFl', | |
| 'expirationFl', | |
| 'privateMarketingConsentOptionFl', | |
| ], $memberData | |
| ); | |
변경 전MemberVO.php
| protected $ex1, $ex2, $ex3, $ex4, $ex5, $ex6; | |
| protected $privateApprovalFl; | |
| protected $privateApprovalOptionFl; | |
| protected $privateOfferFl; | |
| protected $privateConsignFl; | |
| protected $foreigner; | |
| $this->privateApprovalOptionFl = $privateApprovalOptionFl; | |
| } | |
| /** | |
| * @param mixed $privateOfferFl | |
| */ | |
변경 후MemberVO.php
| protected $ex1, $ex2, $ex3, $ex4, $ex5, $ex6; | |
| protected $privateApprovalFl; | |
| protected $privateApprovalOptionFl; | |
| protected $privateMarketingConsentOptionFl; | |
| protected $privateMarketingConsentNoticePopupDt; | |
| protected $privateOfferFl; | |
| protected $privateConsignFl; | |
| protected $foreigner; | |
| $this->privateApprovalOptionFl = $privateApprovalOptionFl; | |
| } | |
| /** | |
| * @param mixed $privateMarketingConsentOptionFl 마케팅 목적 개인정보 수집 및 이용 동의 | |
| */ | |
| public function setPrivateMarketingConsentOptionFl($privateMarketingConsentOptionFl) | |
| { | |
| $this->privateMarketingConsentOptionFl = $privateMarketingConsentOptionFl; | |
| } | |
| /** | |
| * @param mixed $privateMarketingConsentNoticePopupDt 마케팅 목적 개인정보 수집 및 이용 동의 안내 팝업 노출 일시 | |
| */ | |
| public function setPrivateMarketingConsentNoticePopupDt($privateMarketingConsentNoticePopupDt) | |
| { | |
| $this->privateMarketingConsentNoticePopupDt = $privateMarketingConsentNoticePopupDt; | |
| } | |
| /** | |
| * @param mixed $maillingFl 이메일 수신 동의 | |
| */ | |
| public function setMaillingFl($maillingFl) | |
| { | |
| $this->maillingFl = $maillingFl; | |
| } | |
| /** | |
| * @param mixed $smsFl 모바일 메시지 수신 동의 | |
| */ | |
| public function setSmsFl($smsFl) | |
| { | |
| $this->smsFl = $smsFl; | |
| } | |
| /** | |
| * @param mixed $privateOfferFl | |
| */ | |
변경 전MyPage.php
| $requestParams['privateConsignFl'] = json_encode($agreementData['privateConsignFl'], JSON_UNESCAPED_SLASHES); | |
| $requestParams['privateOfferFl'] = json_encode($agreementData['privateOfferFl'], JSON_UNESCAPED_SLASHES); | |
| $passValidation = isset($memberSession['memPw']) == false && $memberSession['snsJoinFl'] == 'y'; | |
| $requestParams = $this->validateMemberByModification($requestParams, $passValidation); | |
| $addExclude = [ | |
| $v->add('privateApprovalOptionFl', '', false, '{' . __('개인정보 수집 및 이용') . '}'); | |
| $v->add('privateOfferFl', '', false, '{' . __('개인정보동의 제3자 제공') . '}'); | |
| $v->add('privateConsignFl', '', false, '{' . __('개인정보동의 취급업무 위탁') . '}'); | |
| if (StringUtils::strIsSet($requestParams['memPw'], '') !== '') { | |
| \Component\Member\MemberValidation::validateMemberPassword($requestParams['memPw']); | |
| $v->add('memPw', '', true, '{' . __('비밀번호') . '}'); | |
| } else { | |
| $requestParams['privateOfferFl'] = $arrprivateOffer; | |
| } | |
| return $requestParams; | |
| } | |
| } | |
변경 후MyPage.php
| $requestParams['privateConsignFl'] = json_encode($agreementData['privateConsignFl'], JSON_UNESCAPED_SLASHES); | |
| $requestParams['privateOfferFl'] = json_encode($agreementData['privateOfferFl'], JSON_UNESCAPED_SLASHES); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의는 사용 시에만 setAgreementData 세팅 (미사용 시 미포함 → 컬럼값 갱신 안 함, 기존값 유지) | |
| if (array_key_exists('privateMarketingConsentOptionFl', $agreementData)) { | |
| $requestParams['privateMarketingConsentOptionFl'] = $agreementData['privateMarketingConsentOptionFl']; | |
| } | |
| $passValidation = isset($memberSession['memPw']) == false && $memberSession['snsJoinFl'] == 'y'; | |
| $requestParams = $this->validateMemberByModification($requestParams, $passValidation); | |
| $addExclude = [ | |
| $v->add('privateApprovalOptionFl', '', false, '{' . __('개인정보 수집 및 이용') . '}'); | |
| $v->add('privateOfferFl', '', false, '{' . __('개인정보동의 제3자 제공') . '}'); | |
| $v->add('privateConsignFl', '', false, '{' . __('개인정보동의 취급업무 위탁') . '}'); | |
| $v->add('privateMarketingConsentOptionFl', '', false, '{' . __('마케팅 목적 개인정보 수집 및 이용 동의') . '}'); | |
| if (StringUtils::strIsSet($requestParams['memPw'], '') !== '') { | |
| \Component\Member\MemberValidation::validateMemberPassword($requestParams['memPw']); | |
| $v->add('memPw', '', true, '{' . __('비밀번호') . '}'); | |
| } else { | |
| $requestParams['privateOfferFl'] = $arrprivateOffer; | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 (사용 시에만 동의 'y' / 미동의 'n' 저장. 미사용 시 빈값 유지 - 로그인 안내 팝업 조건) | |
| $privateMarketingMemberData = $inform->getInformDataArray(BuyerInformCode::PRIVATE_MARKETING_MEMBER); | |
| if (($privateMarketingMemberData[0]['modeFl'] ?? 'n') === 'y') { | |
| $requestParams['privateMarketingConsentOptionFl'] = (($requestParams['privateMarketingConsentOptionFl'] ?? '') === 'y') ? 'y' : 'n'; | |
| } | |
| return $requestParams; | |
| } | |
| } | |
변경 전MemberUtil.php
| } | |
| $joinField = \Component\Policy\JoinItemPolicy::getInstance()->getPolicy($mallSno); | |
| $html[] = '<tr>'; | |
| for ($i = 1; $i < 7; $i++) { | |
| $key = 'ex' . $i; | |
| $value = $joinField[$key]; | |
| continue; | |
| } | |
| if ($value['name']) { | |
| $title .= '<br /><span class="nobold">(' . $value['name'] . ')</span>'; | |
| } | |
| if ($i != 1 && $i % 2 != 0) { | |
| $html[] = '</tr><tr>'; | |
| } | |
| $html[] = '<th class="input_title r_space ex">' . $title . '</th>'; | |
| $html[] = '<td>'; | |
| $tmpArray = array_map('trim', explode(',', $value['value'])); | |
| switch ($value['type']) { | |
| default : | |
| $html[] = '<input type="text" name="' . $key . '" class="form-control" value="' . $fieldValue[$key] . '"/>'; | |
| break; | |
| case 'SELECT': | |
| $html[] = gd_select_box($key, $key, gd_array_change_key_value($tmpArray), null, $fieldValue[$key], '=선택='); | |
| break; | |
| case 'RADIO': | |
| $html[] = gd_radio_box($key, array_combine(gd_array_values($tmpArray), gd_array_values($tmpArray)), $fieldValue[$key]); | |
| break; | |
| case 'CHECKBOX': | |
| $html[] = gd_check_box($key . '[]', array_combine(gd_array_values($tmpArray), gd_array_values($tmpArray)), $fieldValue[$key]); | |
| break; | |
| } | |
| $html[] = '</td>'; | |
| } | |
| return gd_implode('', $html); | |
| } | |
| /** | |
| * 로그인 되었는 지를 체크 (회원/비회원) | |
| * | |
| $data['agreementInfoFl'] = gd_isset($arrData['agreementInfoFl'], 'n'); | |
| $data['privateApprovalFl'] = gd_isset($arrData['privateApprovalFl'], 'n'); | |
| $data['under14ConsentFl'] = gd_isset($arrData['under14ConsentFl'], 'n'); | |
| //이용약관 체크값 설정 | |
| $myPage = \App::load('\\Component\\Member\\MyPage'); | |
| $data['privateApprovalOptionFl'] = gd_isset($agreementData['privateApprovalOptionFl']); | |
| $data['privateOfferFl'] = gd_isset($agreementData['privateOfferFl']); | |
| $data['privateConsignFl'] = gd_isset($agreementData['privateConsignFl']); | |
| // 인증설정체크해서 데이터 추가 useDataJoinFl | |
| $dreamInfo = gd_policy('member.auth_cellphone'); | |
| $params['sexFl'] = $params['sexFl'] ?? ''; | |
| $params['maillingFl'] = $params['maillingFl'] ?? ''; | |
| $params['smsFl'] = $params['smsFl'] ?? ''; | |
| $params['calendarFl'] = $params['calendarFl'] ?? ''; | |
| $params['expirationFl'] = $params['expirationFl'] ?? ''; | |
| $checked['sexFl'][$params['sexFl']] = | |
| $checked['maillingFl'][$params['maillingFl']] = | |
| $checked['smsFl'][$params['smsFl']] = | |
| $checked['calendarFl'][$params['calendarFl']] = | |
| $checked['expirationFl'][$params['expirationFl']] = 'checked="checked"'; | |
변경 후MemberUtil.php
| } | |
| $joinField = \Component\Policy\JoinItemPolicy::getInstance()->getPolicy($mallSno); | |
| $html = []; | |
| for ($i = 1; $i < 7; $i++) { | |
| $key = 'ex' . $i; | |
| $value = $joinField[$key]; | |
| continue; | |
| } | |
| if ($value['name']) { | |
| $title .= '<span class="nobold">(' . $value['name'] . ')</span>'; | |
| } | |
| $html[] = '<tr>'; | |
| $html[] = '<th><div class="ncua-align-items-center ncua-flex-column ncua-align-items-start">' . $title . '</div></th>'; | |
| $html[] = '<td><div class="ncua-flex-gap">'; | |
| $tmpArray = array_map('trim', explode(',', $value['value'])); | |
| switch ($value['type']) { | |
| case 'SELECT': | |
| $html[] = '<span class="ncua-select ncua-select--xs">'; | |
| $html[] = '<span class="ncua-select__content">'; | |
| $html[] = gd_select_box($key, $key, gd_array_change_key_value($tmpArray), null, $fieldValue[$key], '=선택=', null, 'ncua-select__tag'); | |
| $html[] = '</span>'; | |
| $html[] = '</span>'; | |
| break; | |
| case 'RADIO': | |
| $html[] = gd_radio_box_ncua($key, array_combine(gd_array_values($tmpArray), gd_array_values($tmpArray)), $fieldValue[$key]); | |
| break; | |
| case 'CHECKBOX': | |
| $html[] = gd_check_box_ncua($key . '[]', array_combine(gd_array_values($tmpArray), gd_array_values($tmpArray)), $fieldValue[$key]); | |
| break; | |
| default : | |
| $html[] = '<div class="ncua-input ncua-input--xs ncua-input-width-320">'; | |
| $html[] = '<div class="ncua-input__content">'; | |
| $html[] = '<div class="ncua-input__field ncua-input__field--xs">'; | |
| $html[] = '<input type="text" name="' . $key . '" value="' . gd_htmlspecialchars($fieldValue[$key]) . '" placeholder="추가정보를 입력하세요."/>'; | |
| $html[] = '</div>'; | |
| $html[] = '</div>'; | |
| $html[] = '</div>'; | |
| break; | |
| } | |
| $html[] = '</div></td>'; | |
| $html[] = '</tr>'; | |
| } | |
| return gd_implode('', $html); | |
| } | |
| /** | |
| * 약관 동의 표시 항목 생성 (informNm + 동의함/동의안함 라벨) | |
| * | |
| * 개인정보 수집·이용/취급위탁/제3자 제공/마케팅 동의 등 약관 표시 블록을 정형화한다. | |
| * | |
| * @param array $informList 약관 목록 (각 항목에 sno, informNm 포함. modeFl 이 'y' 아니면 '사용안함' 표기) | |
| * @param array $consentBySno 동의 상태 맵 (sno => 'y'/'n') | |
| * @param bool $denyWhenMissing 미응답(y/n 아님)을 '동의안함'으로 표시할지 여부. false면 해당 항목 스킵 | |
| * @return array [['informNm' => string, 'label' => string, 'unused'? => bool], ...] (unused=true 면 미사용 약관 → 항목명 없이 '사용안함'만 표기) | |
| */ | |
| public static function makeConsentItems(array $informList, array $consentBySno, bool $denyWhenMissing = false, string $agreementDt = ''): array | |
| { | |
| $items = []; | |
| foreach ($informList as $inform) { | |
| // 개별 약관 미사용(modeFl != 'y')이면 동의 여부와 무관하게 '사용안함' 표기 | |
| if (($inform['modeFl'] ?? 'y') !== 'y') { | |
| $items[] = ['informNm' => $inform['informNm'], 'label' => '사용안함', 'unused' => true]; | |
| continue; | |
| } | |
| $flag = $consentBySno[$inform['sno']] ?? ''; | |
| if ($flag === 'y') { | |
| // 동의: 년월일시분초까지 표기 | |
| $label = '동의함' . ($agreementDt !== '' ? '(' . DateTimeUtils::dateFormat('Y-m-d H:i:s', $agreementDt) . ')' : ''); | |
| } elseif ($flag === 'n' || $denyWhenMissing) { | |
| // 미동의: 년월일까지만 표기 (일시 없거나 미응답이면 날짜 생략) | |
| $label = '동의안함' . (($agreementDt !== '' && $flag === 'n') ? '(' . DateTimeUtils::dateFormat('Y-m-d', $agreementDt) . ')' : ''); | |
| } else { | |
| continue; | |
| } | |
| $items[] = ['informNm' => $inform['informNm'], 'label' => $label]; | |
| } | |
| return $items; | |
| } | |
| /** | |
| * 회원 약관 동의 표시용 행 데이터 생성. 약관 행 설정 배열을 받아 뷰에서 그대로 출력할 표시용 배열을 반환한다 (HTML 미생성 — 마크업은 뷰가 담당). | |
| * 약관이 늘어도 호출부에서 배열 항목만 추가하면 되고 메서드 시그니처는 불변. | |
| * | |
| * @param array $agreements 약관 행 목록. 각 항목: | |
| * - title string 제목 (뷰 <th> 출력용) | |
| * - tooltipSeq string data-tooltip-seq 값(선택) | |
| * - use bool 약관 사용/표시 여부 (false면 '사용안함') | |
| * - informs array 약관 목록 (sno, informNm) — use=true 일 때만 참조 | |
| * - flags mixed 동의 상태. sno=>('y'/'n') 배열(개인정보 항목별) 또는 단일 'y'/'n' 문자열(마케팅) | |
| * - denyWhenMissing bool 미응답(y/n 아님)을 '동의안함'으로 표시할지. false면 해당 항목 스킵 | |
| * - agreementDt string 동의/미동의 일시(선택). 지정 시 동의함(초까지)/동의안함(날짜까지)에 괄호로 병기. 컬럼 공통 값 | |
| * @return array 표시용 행 목록. 각 항목: [title, tooltipSeq, lines(표시 문자열 배열)] | |
| */ | |
| public static function buildPrivateAgreementRows(array $agreements): array | |
| { | |
| $rows = []; | |
| foreach ($agreements as $agreement) { | |
| $lines = []; | |
| if (!empty($agreement['use'])) { | |
| $informs = $agreement['informs'] ?? []; | |
| $flags = $agreement['flags'] ?? []; | |
| // 단일 플래그 문자열이면 전 항목에 동일 적용하도록 sno 맵으로 변환 | |
| if (!is_array($flags)) { | |
| $singleFlag = (string) $flags; | |
| $flags = []; | |
| foreach ($informs as $inform) { | |
| $flags[$inform['sno']] = $singleFlag; | |
| } | |
| } | |
| $agreementDt = (string) ($agreement['agreementDt'] ?? ''); | |
| $unusedShown = false; | |
| foreach (self::makeConsentItems($informs, $flags, !empty($agreement['denyWhenMissing']), $agreementDt) as $item) { | |
| if (!empty($item['unused'])) { | |
| // 미사용 약관(modeFl != 'y')은 항목명/동의여부 없이 '사용안함'만, 그룹당 1회만 표기 | |
| if ($unusedShown) { | |
| continue; | |
| } | |
| $unusedShown = true; | |
| $lines[] = '사용안함'; | |
| } else { | |
| $lines[] = '- ' . $item['informNm'] . ' : ' . $item['label']; | |
| } | |
| } | |
| } else { | |
| $lines[] = '사용안함'; | |
| } | |
| $rows[] = [ | |
| 'title' => $agreement['title'] ?? '', | |
| 'tooltipSeq' => $agreement['tooltipSeq'] ?? '', | |
| 'lines' => $lines, | |
| ]; | |
| } | |
| return $rows; | |
| } | |
| /** | |
| * 광고성 수신 동의(이메일/모바일 메시지) 표시용 라인 데이터 생성. 채널 사용여부 + 수신 flag + 최종 수신동의일(es_memberHistory 파생)로 | |
| * 동의함(초까지)/동의안함(날짜까지) 라벨을 조립한다 (HTML 미생성 — 마크업은 뷰가 담당). | |
| * | |
| * @param array $advertisingReceive gd_policy('member.advertisingReceive') — email.use / mobile.use ('y'/'n') | |
| * @param array $data 회원 데이터 (maillingFl, smsFl, lastReceiveAgreementDt[mail|sms], entryDt) | |
| * @return array 표시 문자열 배열. 채널 모두 미사용이면 ['사용안함'] | |
| */ | |
| public static function buildAdvertisingReceiveLines(array $advertisingReceive, array $data): array | |
| { | |
| $mailUse = (($advertisingReceive['email']['use'] ?? 'n') === 'y'); | |
| $smsUse = (($advertisingReceive['mobile']['use'] ?? 'n') === 'y'); | |
| if (!$mailUse && !$smsUse) { | |
| return ['사용안함']; | |
| } | |
| $channels = []; | |
| if ($mailUse) { | |
| $channels[] = ['label' => '이메일', 'flag' => $data['maillingFl'] ?? 'n', 'dt' => $data['lastReceiveAgreementDt']['mail'] ?? ($data['entryDt'] ?? '')]; | |
| } | |
| if ($smsUse) { | |
| $channels[] = ['label' => '모바일 메시지', 'flag' => $data['smsFl'] ?? 'n', 'dt' => $data['lastReceiveAgreementDt']['sms'] ?? ($data['entryDt'] ?? '')]; | |
| } | |
| $lines = []; | |
| foreach ($channels as $channel) { | |
| // 동의: 년월일시분초까지 / 미동의: 년월일까지 (일시 없으면 괄호 생략) | |
| if ($channel['flag'] === 'y') { | |
| $label = '동의함' . ($channel['dt'] !== '' ? '(' . DateTimeUtils::dateFormat('Y-m-d H:i:s', $channel['dt']) . ')' : ''); | |
| } else { | |
| $label = '동의안함' . ($channel['dt'] !== '' ? '(' . DateTimeUtils::dateFormat('Y-m-d', $channel['dt']) . ')' : ''); | |
| } | |
| $lines[] = '- ' . $channel['label'] . ' : ' . $label; | |
| } | |
| return $lines; | |
| } | |
| /** | |
| * 비밀번호 입력 필드 placeholder 문구 생성 (회원 등록/수정 공통) | |
| * | |
| * @param array $joinField 회원가입 항목 정책 (passwordCombineFl, memPw.minlen/maxlen) | |
| * @return string 조합 규칙 + 길이 안내 문구 | |
| */ | |
| public static function buildPasswordPlaceholder(array $joinField): string | |
| { | |
| $combine = match ($joinField['passwordCombineFl'] ?? '') { | |
| 'engNum' => '영문대문자/영문소문자/숫자 중 2개 이상 포함', | |
| 'engNumEtc' => '영문대문자/영문소문자/숫자/특수문자 중 3개 이상 포함', | |
| default => '영문대문자/영문소문자 or 숫자', | |
| }; | |
| return $combine . ', ' . $joinField['memPw']['minlen'] . '~' . $joinField['memPw']['maxlen'] . '자'; | |
| } | |
| /** | |
| * 로그인 되었는 지를 체크 (회원/비회원) | |
| * | |
| $data['agreementInfoFl'] = gd_isset($arrData['agreementInfoFl'], 'n'); | |
| $data['privateApprovalFl'] = gd_isset($arrData['privateApprovalFl'], 'n'); | |
| $data['under14ConsentFl'] = gd_isset($arrData['under14ConsentFl'], 'n'); | |
| // 광고성 수신 동의 (이메일 수신 동의 / 모바일 메시지 수신 동의) | |
| $data['maillingFl'] = gd_isset($arrData['maillingFl'], 'n'); | |
| $data['smsFl'] = gd_isset($arrData['smsFl'], 'n'); | |
| //이용약관 체크값 설정 | |
| $myPage = \App::load('\\Component\\Member\\MyPage'); | |
| $data['privateApprovalOptionFl'] = gd_isset($agreementData['privateApprovalOptionFl']); | |
| $data['privateOfferFl'] = gd_isset($agreementData['privateOfferFl']); | |
| $data['privateConsignFl'] = gd_isset($agreementData['privateConsignFl']); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 | |
| $data['privateMarketingConsentOptionFl'] = gd_isset($agreementData['privateMarketingConsentOptionFl']); | |
| // 인증설정체크해서 데이터 추가 useDataJoinFl | |
| $dreamInfo = gd_policy('member.auth_cellphone'); | |
| $params['sexFl'] = $params['sexFl'] ?? ''; | |
| $params['maillingFl'] = $params['maillingFl'] ?? ''; | |
| $params['smsFl'] = $params['smsFl'] ?? ''; | |
| $params['privateMarketingConsentOptionFl'] = $params['privateMarketingConsentOptionFl'] ?? ''; | |
| $params['calendarFl'] = $params['calendarFl'] ?? ''; | |
| $params['expirationFl'] = $params['expirationFl'] ?? ''; | |
| $checked['sexFl'][$params['sexFl']] = | |
| $checked['maillingFl'][$params['maillingFl']] = | |
| $checked['smsFl'][$params['smsFl']] = | |
| $checked['privateMarketingConsentOptionFl'][$params['privateMarketingConsentOptionFl']] = | |
| $checked['calendarFl'][$params['calendarFl']] = | |
| $checked['expirationFl'][$params['expirationFl']] = 'checked="checked"'; | |
변경 전MemberModifyController.php
| use Framework\Debug\Exception\AlertBackException; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\StringUtils; | |
| /** | |
| $memberData = []; | |
| $memberService->getMemberDataWithChecked($memNo, $memberData, $checked); | |
| $memberData = gd_array_merge($memberData, $memberService->getLastAgreementNotificationByMember($memNo)); | |
| $privateApprovalOption = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_APPROVAL_OPTION, 'sno,informNm,content', true, $memberData['mallSno']); | |
| $privateOffer = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_OFFER, 'sno,informNm,content', true, $memberData['mallSno']); | |
| $privateConsign = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_CONSIGN, 'sno,informNm,content', true, $memberData['mallSno']); | |
| $memberData = gd_array_merge($memberData, $historyService->getLastReceiveAgreementByMember($memNo)); | |
| $memberHistory = $historyService->getMemberHistory($memNo, $request->get()->get('page', 1), $request->get()->get('pageNum', 10)); | |
| $memberData['recommendCnt'] = $memberService->getRecommendCount($memberData['memId']); | |
| if ($memberData['rncheck'] == 'realname') { | |
| $additionalCertification[$key]['file'] = $companyCertification->getCertificationByMemNoAndType($memNo, $key); | |
| } | |
| $this->setData('mode', 'modify'); | |
| $this->setData('joinField', \Component\Member\Util\MemberUtil::getJoinField($memberData['mallSno'])); | |
| $this->setData('htmlExtra', \Component\Member\Util\MemberUtil::makeExtraField($memberData)); | |
| $this->setData('data', $memberData); | |
| $this->setData('checked', $checked); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateOffer', $privateOffer); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('groupCouponConditionManual', gd_policy('member.group')['couponConditionManual']); | |
| $this->setData('hidePasswordBlock', $hidePasswordBlock); | |
| $this->setData('certification', $certification); | |
변경 후MemberModifyController.php
| use Framework\Debug\Exception\AlertBackException; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\SkinUtils; | |
| use Framework\Utility\StringUtils; | |
| /** | |
| $memberData = []; | |
| $memberService->getMemberDataWithChecked($memNo, $memberData, $checked); | |
| $memberData = gd_array_merge($memberData, $memberService->getLastAgreementNotificationByMember($memNo)); | |
| $privateApprovalOption = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_APPROVAL_OPTION, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateOffer = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_OFFER, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateConsign = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_CONSIGN, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateMarketingMember = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_MARKETING_MEMBER, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateMarketingMemberUse = (($privateMarketingMember[0]['modeFl'] ?? 'n') === 'y'); | |
| // 개인정보 동의 항목별 마지막 변경 일시(컬럼 공통). 이력 없으면 가입일(entryDt) 폴백 | |
| $privateAgreementDt = $historyService->getLastPrivateAgreementDateByMember((int) $memNo); | |
| $memberEntryDt = $memberData['entryDt'] ?? ''; | |
| // 약관 동의 표시 행 조립 (개인정보 항목별/마케팅). 표시용 데이터 변환은 MemberUtil::buildPrivateAgreementRows | |
| $privateAgreements = [ | |
| ['title' => '개인정보 수집·이용', 'tooltipSeq' => '036', 'use' => is_array($memberData['privateApprovalOptionFl'] ?? null), 'informs' => $privateApprovalOption, 'flags' => $memberData['privateApprovalOptionFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateApprovalOptionFl'] ?? $memberEntryDt], | |
| ['title' => '개인정보 취급위탁', 'tooltipSeq' => '037', 'use' => is_array($memberData['privateConsignFl'] ?? null), 'informs' => $privateConsign, 'flags' => $memberData['privateConsignFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateConsignFl'] ?? $memberEntryDt], | |
| ['title' => '개인정보 제3자 제공', 'tooltipSeq' => '038', 'use' => is_array($memberData['privateOfferFl'] ?? null), 'informs' => $privateOffer, 'flags' => $memberData['privateOfferFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateOfferFl'] ?? $memberEntryDt], | |
| ['title' => '마케팅 목적 개인정보 수집 및 이용 동의', 'tooltipSeq' => '039', 'use' => $privateMarketingMemberUse, 'informs' => $privateMarketingMember, 'flags' => $memberData['privateMarketingConsentOptionFl'] ?? '', 'denyWhenMissing' => true, 'agreementDt' => $privateAgreementDt['privateMarketingConsentOptionFl'] ?? $memberEntryDt], | |
| ]; | |
| $advertisingReceiveChannelUse = $buyerInformService->getAdvertisingReceiveChannelUse($memberData['mallSno']); | |
| $advertisingReceive = [ | |
| 'email' => ['use' => $advertisingReceiveChannelUse['mail']], | |
| 'mobile' => ['use' => $advertisingReceiveChannelUse['sms']], | |
| ]; | |
| $memberData = gd_array_merge($memberData, $historyService->getLastReceiveAgreementByMember($memNo)); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의/거부일 (없으면 '-') | |
| $memberData['privateMktAgreementDt'] = $memberData['lastReceiveAgreementDt']['privateMkt'] ?? '-'; | |
| $memberHistory = $historyService->getMemberHistory($memNo, $request->get()->get('page', 1), $request->get()->get('pageNum', 10)); | |
| $memberData['recommendCnt'] = $memberService->getRecommendCount($memberData['memId']); | |
| if ($memberData['rncheck'] == 'realname') { | |
| $additionalCertification[$key]['file'] = $companyCertification->getCertificationByMemNoAndType($memNo, $key); | |
| } | |
| // NCDS 템플릿 설정 | |
| $this->setData('adminBodySubClass', 'ncds'); | |
| $this->setData('mode', 'modify'); | |
| $this->setData('callPrefixList', SkinUtils::getCallPrefixList()); | |
| $joinField = \Component\Member\Util\MemberUtil::getJoinField($memberData['mallSno']); | |
| $this->setData('joinField', $joinField); | |
| $this->setData('passwordPlaceholder', \Component\Member\Util\MemberUtil::buildPasswordPlaceholder($joinField)); | |
| $this->setData('htmlExtra', \Component\Member\Util\MemberUtil::makeExtraField($memberData)); | |
| $this->setData('data', $memberData); | |
| $this->setData('checked', $checked); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateOffer', $privateOffer); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('privateMarketingMember', $privateMarketingMember); | |
| $this->setData('privateMarketingMemberUse', $privateMarketingMemberUse); | |
| $this->setData('privateAgreementRows', \Component\Member\Util\MemberUtil::buildPrivateAgreementRows($privateAgreements)); | |
| $this->setData('advertisingReceive', $advertisingReceive); | |
| $this->setData('advertisingReceiveLines', \Component\Member\Util\MemberUtil::buildAdvertisingReceiveLines($advertisingReceive, $memberData)); | |
| $this->setData('groupCouponConditionManual', gd_policy('member.group')['couponConditionManual']); | |
| $this->setData('hidePasswordBlock', $hidePasswordBlock); | |
| $this->setData('certification', $certification); | |
변경 전MemberPsController.php
| use Framework\Debug\Exception\LayerException; | |
| use Origin\Service\Policy\Member\JoinPolicyService; | |
| use Origin\Service\Member\KakaoSync\KakaoSyncSettingService; | |
| /** | |
| * Class 회원 처리 | |
| switch ($requestAllParams['mode']) { | |
| case 'register': | |
| $memberService->register(new MemberVO($requestPostParams)); | |
| $this->json(__("회원등록을 성공하였습니다.")); | |
| break; | |
| case 'modify': | |
| $memberAdminService->modifyMemberData($requestAllParams); | |
| $this->json(__('저장이 완료되었습니다.')); | |
| break; | |
| throw new Exception(__('요청을 처리할 페이지를 찾을 수 없습니다.'), 404); | |
| break; | |
| } | |
| } catch (Exception $e) { | |
| if ($request->isAjax() === true) { | |
| switch ($e->getCode()) { | |
변경 후MemberPsController.php
| use Framework\Debug\Exception\LayerException; | |
| use Origin\Service\Policy\Member\JoinPolicyService; | |
| use Origin\Service\Member\KakaoSync\KakaoSyncSettingService; | |
| use Respect\Validation\Exceptions\NestedValidationException; | |
| use Respect\Validation\Validator; | |
| /** | |
| * Class 회원 처리 | |
| switch ($requestAllParams['mode']) { | |
| case 'register': | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 형식 검증 | |
| Validator::arrayVal() | |
| ->key('privateMarketingConsentOptionFl', Validator::in(['y', 'n']), false) | |
| ->assert($requestAllParams); | |
| $memberService->register(new MemberVO($requestPostParams)); | |
| $this->json(__("회원등록을 성공하였습니다.")); | |
| break; | |
| case 'modify': | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 형식 검증 | |
| Validator::arrayVal() | |
| ->key('privateMarketingConsentOptionFl', Validator::in(['y', 'n']), false) | |
| ->assert($requestAllParams); | |
| $memberAdminService->modifyMemberData($requestAllParams); | |
| $this->json(__('저장이 완료되었습니다.')); | |
| break; | |
| throw new Exception(__('요청을 처리할 페이지를 찾을 수 없습니다.'), 404); | |
| break; | |
| } | |
| } catch (NestedValidationException $e) { | |
| \Logger::channel('member')->warning('member.validate.fail', [ | |
| 'mode' => $requestAllParams['mode'] ?? '', | |
| 'errors' => $e->getMessages(), | |
| ]); | |
| if ($request->isAjax()) { | |
| $this->json( | |
| data: [ | |
| 'success' => false, | |
| 'message' => __('잘못된 요청입니다.'), | |
| 'data' => [] | |
| ], | |
| ); | |
| } else { | |
| throw new LayerException(__('잘못된 요청입니다.'), $e->getCode(), $e, null, 3000); | |
| } | |
| } catch (Exception $e) { | |
| if ($request->isAjax() === true) { | |
| switch ($e->getCode()) { | |
변경 전MemberRegisterController.php
| use Component\Member\Group\Util as GroupUtil; | |
| use Component\Member\MemberVO; | |
| use Component\Member\Util\MemberUtil; | |
| /** | |
| * Class 회원 등록 | |
| $companyCertification = \App::getInstance(\Component\Member\Company\CompanyCertification::class); | |
| $certificationMaxFileSize = $companyCertification->getCompanyCertificationFileSize(); | |
| $this->setData('mode', 'register'); | |
| $this->setData('joinField', $joinField); | |
| $this->setData('htmlExtra', MemberUtil::makeExtraField()); | |
| $this->setData('data', $member); | |
| $this->setData('checked', $vo->toChecked()); | |
| $this->setData('certificationMaxFileSize', $certificationMaxFileSize); | |
변경 후MemberRegisterController.php
| use Component\Member\Group\Util as GroupUtil; | |
| use Component\Member\MemberVO; | |
| use Component\Member\Util\MemberUtil; | |
| use Framework\Utility\SkinUtils; | |
| /** | |
| * Class 회원 등록 | |
| $companyCertification = \App::getInstance(\Component\Member\Company\CompanyCertification::class); | |
| $certificationMaxFileSize = $companyCertification->getCompanyCertificationFileSize(); | |
| // 신규 회원은 동의 이력이 없으므로 전부 '사용안함' | |
| $privateAgreements = [ | |
| ['title' => '개인정보 수집·이용', 'use' => false], | |
| ['title' => '개인정보 취급위탁', 'use' => false], | |
| ['title' => '개인정보 제3자 제공', 'use' => false], | |
| ['title' => '마케팅 목적 개인정보 수집 및 이용 동의', 'use' => false], | |
| ]; | |
| $buyerInformService = \App::getInstance('BuyerInform'); | |
| if (!is_object($buyerInformService)) { | |
| $buyerInformService = new \Component\Agreement\BuyerInform(); | |
| } | |
| $mallSno = (int) (\Component\Mall\Mall::getSession('sno') ?: DEFAULT_MALL_NUMBER); | |
| // 신규 회원은 동의 이력이 없으므로 광고성 수신 동의도 '사용안함' (몰 설정과 무관) | |
| $advertisingReceive = [ | |
| 'email' => ['use' => 'n'], | |
| 'mobile' => ['use' => 'n'], | |
| ]; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 약관 사용 여부 (약관 사용 시에만 노출) | |
| $privateMarketingMember = $buyerInformService->getInformDataArray(\Component\Agreement\BuyerInformCode::PRIVATE_MARKETING_MEMBER, 'sno,informNm,content,modeFl', true, $mallSno); | |
| $privateMarketingMemberUse = (($privateMarketingMember[0]['modeFl'] ?? 'n') === 'y'); | |
| // NCDS 템플릿 설정 | |
| $this->setData('adminBodySubClass', 'ncds'); | |
| $this->setData('mode', 'register'); | |
| $this->setData('callPrefixList', SkinUtils::getCallPrefixList()); | |
| $this->setData('joinField', $joinField); | |
| $this->setData('passwordPlaceholder', MemberUtil::buildPasswordPlaceholder($joinField)); | |
| $this->setData('htmlExtra', MemberUtil::makeExtraField()); | |
| $this->setData('privateAgreementRows', MemberUtil::buildPrivateAgreementRows($privateAgreements)); | |
| $this->setData('advertisingReceive', $advertisingReceive); | |
| $this->setData('advertisingReceiveLines', MemberUtil::buildAdvertisingReceiveLines($advertisingReceive, $member)); | |
| $this->setData('privateMarketingMemberUse', $privateMarketingMemberUse); | |
| $this->setData('data', $member); | |
| $this->setData('checked', $vo->toChecked()); | |
| $this->setData('certificationMaxFileSize', $certificationMaxFileSize); | |
변경 전BaseAgreementWithPrivateController.php
| $privateApprovalTableOption = $agreementWithPrivateUtil->getTableByPrivateApprovalOption($mallSno); | |
| $privateConsignTable = $agreementWithPrivateUtil->getTableByPrivateConsign($mallSno); | |
| $privateOfferTable = $agreementWithPrivateUtil->getTableByPrivateOffer($mallSno); | |
| $privateGuestOrder = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_ORDER, $mallSno); | |
| $privateGuestBoardWrite = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_BOARD_WRITE, $mallSno); | |
| $privateGuestCommentWrite = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_COMMENT_WRITE, $mallSno); | |
| $this->setData('privateApprovalTableOption', $privateApprovalTableOption); | |
| $this->setData('privateConsignTable', $privateConsignTable); | |
| $this->setData('privateOfferTable', $privateOfferTable); | |
| $this->setData('privateGuestOrderContent', $privateGuestOrder['content']); | |
| $this->setData('privateGuestBoardWriteContent', $privateGuestBoardWrite['content']); | |
| $this->setData('privateGuestCommentWriteContent', $privateGuestCommentWrite['content']); | |
변경 후BaseAgreementWithPrivateController.php
| $privateApprovalTableOption = $agreementWithPrivateUtil->getTableByPrivateApprovalOption($mallSno); | |
| $privateConsignTable = $agreementWithPrivateUtil->getTableByPrivateConsign($mallSno); | |
| $privateOfferTable = $agreementWithPrivateUtil->getTableByPrivateOffer($mallSno); | |
| $privateMarketingMember = $buyerInform->getInformData(BuyerInformCode::PRIVATE_MARKETING_MEMBER, $mallSno); | |
| $advertisingReceive = $buyerInform->getInformData(BuyerInformCode::ADVERTISING_RECEIVE, $mallSno); | |
| //--- 광고성 수신 동의 채널 사용여부 (es_config member.advertisingReceive) 및 회원가입 항목(이메일/휴대폰번호) 사용여부 | |
| $advertisingReceiveChannel = gd_policy('member.advertisingReceive', $mallSno); | |
| $joinItemPolicy = \App::load('Component\\Policy\\JoinItemPolicy'); | |
| $joinItem = $joinItemPolicy->getPolicy($mallSno); | |
| $privateGuestOrder = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_ORDER, $mallSno); | |
| $privateGuestBoardWrite = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_BOARD_WRITE, $mallSno); | |
| $privateGuestCommentWrite = $buyerInform->getInformData(BuyerInformCode::PRIVATE_GUEST_COMMENT_WRITE, $mallSno); | |
| $this->setData('privateApprovalTableOption', $privateApprovalTableOption); | |
| $this->setData('privateConsignTable', $privateConsignTable); | |
| $this->setData('privateOfferTable', $privateOfferTable); | |
| $this->setData('privateMarketingMember', $privateMarketingMember); | |
| $this->setData('advertisingReceive', $advertisingReceive); | |
| $this->setData('advertisingReceiveMailUse', $advertisingReceiveChannel['email']['use'] ?? 'n'); | |
| $this->setData('advertisingReceiveSmsUse', $advertisingReceiveChannel['mobile']['use'] ?? 'n'); | |
| $this->setData('joinItemEmailUse', $joinItem['email']['use'] ?? 'n'); | |
| $this->setData('joinItemCellPhoneUse', $joinItem['cellPhone']['use'] ?? 'n'); | |
| $this->setData('privateGuestOrderContent', $privateGuestOrder['content']); | |
| $this->setData('privateGuestBoardWriteContent', $privateGuestBoardWrite['content']); | |
| $this->setData('privateGuestCommentWriteContent', $privateGuestCommentWrite['content']); | |
변경 전BaseAgreementWithPrivatePsController.php
| use Framework\Debug\Exception\LayerException; | |
| use Origin\Service\Member\KakaoSync\KakaoSyncSettingService; | |
| use Request; | |
| /** | |
| * Class 약관/개인정보설정 처리 페이지 | |
| break; | |
| // --- 개인정보수집 동의항목 설정 | |
| case 'privateItem': | |
| \DB::begin_tran(); | |
| $removeSnoArray = json_decode(Request::post()->get('removeSno', [])); | |
| $mallSno = gd_isset(Request::post()->get('mallSno'), 1); | |
| foreach ($removeSnoArray as $key => $val) { | |
| $buyerInform->savePrivateConsign(Request::post()->all()); | |
| $buyerInform->savePrivateOffer(Request::post()->all()); | |
| $buyerInform->saveInformData(BuyerInformCode::PRIVATE_MARKETING, Request::post()->get('privateMarketingWriteWrite')); | |
| // 카카오 싱크 update 토필 발행 | |
| $kakaoSyncSettingService = \App::getInstance(KakaoSyncSettingService::class); | |
| $kakaoSyncSettingService->syncSettingWhenSaveTerms(); | |
| \DB::commit(); | |
| $this->json( | |
| [ | |
| 'message' => __('저장이 완료되었습니다.'), | |
| 'code' => 200, | |
| ] | |
| ); | |
| throw new Exception(__('요청을 처리할 페이지를 찾을 수 없습니다.'), 404); | |
| break; | |
| } | |
| } catch (Exception $e) { | |
| \DB::rollback(); | |
| if (Request::isAjax()) { | |
변경 후BaseAgreementWithPrivatePsController.php
| use Framework\Debug\Exception\LayerException; | |
| use Origin\Service\Member\KakaoSync\KakaoSyncSettingService; | |
| use Request; | |
| use Respect\Validation\Exceptions\ValidationException; | |
| use Respect\Validation\Validator; | |
| /** | |
| * Class 약관/개인정보설정 처리 페이지 | |
| break; | |
| // --- 개인정보수집 동의항목 설정 | |
| case 'privateItem': | |
| // post 유효성 검사 | |
| Validator::arrayVal() | |
| ->key('privateMarketingMemberFl', Validator::in(['y', 'n']), false) | |
| ->key('privateMarketingMemberNoticePopupFl', Validator::in(['y', 'n']), false) | |
| ->key('advertisingReceiveMailFl', Validator::in(['y', 'n']), false) | |
| ->key('advertisingReceiveSmsFl', Validator::in(['y', 'n']), false) | |
| ->assert(Request::post()->all()); | |
| \DB::begin_tran(); | |
| // [선택] 광고성 수신 동의 채널을 사용하면서 [선택] 마케팅 목적 개인정보 수집 및 이용 동의를 사용하지 않으면 저장 차단 | |
| $advertisingUse = Request::post()->get('advertisingReceiveMailFl', 'n') === 'y' || Request::post()->get('advertisingReceiveSmsFl', 'n') === 'y'; | |
| if ($advertisingUse && Request::post()->get('privateMarketingMemberFl', 'n') !== 'y') { | |
| throw new Exception(__("[선택] 마케팅 목적 개인정보 수집 및 이용 동의 약관을 '사용'으로 설정해주세요. [선택] 광고성 수신 동의 약관을 사용하기 위해서는 [선택] 마케팅 목적 개인정보 수집 및 이용 동의 약관을 반드시 사용해야 합니다."), 400); | |
| } | |
| $removeSnoArray = json_decode(Request::post()->get('removeSno', [])); | |
| $mallSno = gd_isset(Request::post()->get('mallSno'), 1); | |
| foreach ($removeSnoArray as $key => $val) { | |
| $buyerInform->savePrivateConsign(Request::post()->all()); | |
| $buyerInform->savePrivateOffer(Request::post()->all()); | |
| $buyerInform->saveInformData(BuyerInformCode::PRIVATE_MARKETING, Request::post()->get('privateMarketingWriteWrite')); | |
| $buyerInform->saveInformData(BuyerInformCode::PRIVATE_MARKETING_MEMBER, Request::post()->get('privateMarketingMemberWriteWrite'), $mallSno); | |
| $buyerInform->saveInformData(BuyerInformCode::ADVERTISING_RECEIVE, Request::post()->get('advertisingReceiveWriteWrite'), $mallSno); | |
| $advertisingReceiveChannels = $buyerInform->resolveAdvertisingReceiveChannels(Request::post()->all(), (int)$mallSno); | |
| $policy->setValue('member.advertisingReceive', $advertisingReceiveChannels, $mallSno); | |
| // 카카오 싱크 update 토필 발행 | |
| $kakaoSyncSettingService = \App::getInstance(KakaoSyncSettingService::class); | |
| $kakaoSyncSettingService->syncSettingWhenSaveTerms(); | |
| \DB::commit(); | |
| // [선택] 마케팅 목적 개인정보 수집 및 이용 동의를 사용하면서 [선택] 광고성 수신 동의를 사용하지 않으면 안내 문구 노출 | |
| $message = __('저장이 완료되었습니다.'); | |
| $marketingMemberUse = Request::post()->get('privateMarketingMemberFl', 'n') === 'y'; | |
| $advertisingUse = Request::post()->get('advertisingReceiveMailFl', 'n') === 'y' || Request::post()->get('advertisingReceiveSmsFl', 'n') === 'y'; | |
| if ($marketingMemberUse && !$advertisingUse) { | |
| $message .= ' ' . __('[선택] 마케팅 목적 개인정보 수집 및 이용 동의 약관만 사용하시면 광고성 메시지를 발송할 수 없습니다. 광고성 메시지를 보내시려면 [선택] 광고성 수신 동의 약관도 함께 사용해주세요.'); | |
| } | |
| $this->json( | |
| [ | |
| 'message' => $message, | |
| 'code' => 200, | |
| ] | |
| ); | |
| throw new Exception(__('요청을 처리할 페이지를 찾을 수 없습니다.'), 404); | |
| break; | |
| } | |
| } catch (ValidationException $e) { | |
| \Logger::channel('agreement')->warning(__METHOD__, ['error' => $e->getMessage()]); | |
| $this->json(['error' => ['code' => 400, 'message' => __('잘못된 요청입니다.')]]); | |
| } catch (Exception $e) { | |
| \DB::rollback(); | |
| if (Request::isAjax()) { | |
변경 전MemberCrmDetailController.php
| $session->set(Member::SESSION_MODIFY_MEMBER_INFO, $memberData); | |
| //@formatter:off | |
| $checked = SkinUtils::setChecked(['memberFl', 'appFl', 'maillingFl', 'smsFl', 'sexFl', 'marriFl', 'expirationFl',], $memberData); | |
| //@formatter:on | |
| $memberData['privateApprovalOptionFl'] = json_decode(stripslashes($memberData['privateApprovalOptionFl']), true); | |
| $memberData['privateOfferFl'] = json_decode(stripslashes($memberData['privateOfferFl']), true); | |
| /** @var \Bundle\Component\Agreement\BuyerInform $buyerInform */ | |
| $buyerInform = App::load('\\Component\\Agreement\\BuyerInform'); | |
| $privateApprovalOption = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION, 'sno,informNm,content', true, $memberData['mallSno']); | |
| $privateOffer = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER, 'sno,informNm,content', true, $memberData['mallSno']); | |
| $privateConsign = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN, 'sno,informNm,content', true, $memberData['mallSno']); | |
| // 하이픈 제거 | |
| $memberData['fax'] = str_replace("-", "", $memberData['fax']); | |
| $this->setData('memberData', $memberData); | |
| $this->setData('mode', 'modify'); | |
| $this->setData('modeTxt', '회원수정'); | |
| $this->setData('joinField', MemberUtil::getJoinField($memberData['mallSno'])); | |
| $this->setData('htmlExtra', MemberUtil::makeExtraField($memberData)); | |
| $this->setData('data', $memberData); | |
| $this->setData('checked', $checked); | |
| $this->setData('history', $memberHistory['data']); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateOffer', $privateOffer); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('groupCouponConditionManual', gd_policy('member.group')['couponConditionManual']); | |
| $this->setData('hidePasswordBlock', $hidePasswordBlock); | |
| $this->setData('certification', $certification); | |
변경 후MemberCrmDetailController.php
| $session->set(Member::SESSION_MODIFY_MEMBER_INFO, $memberData); | |
| //@formatter:off | |
| $checked = SkinUtils::setChecked(['memberFl', 'appFl', 'maillingFl', 'smsFl', 'sexFl', 'marriFl', 'expirationFl', 'privateMarketingConsentOptionFl',], $memberData); | |
| //@formatter:on | |
| $memberData['privateApprovalOptionFl'] = json_decode(stripslashes($memberData['privateApprovalOptionFl']), true); | |
| $memberData['privateOfferFl'] = json_decode(stripslashes($memberData['privateOfferFl']), true); | |
| /** @var \Bundle\Component\Agreement\BuyerInform $buyerInform */ | |
| $buyerInform = App::load('\\Component\\Agreement\\BuyerInform'); | |
| $privateApprovalOption = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateOffer = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateConsign = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateMarketingMember = $buyerInform->getInformDataArray(BuyerInformCode::PRIVATE_MARKETING_MEMBER, 'sno,informNm,content,modeFl', true, $memberData['mallSno']); | |
| $privateMarketingMemberUse = (($privateMarketingMember[0]['modeFl'] ?? 'n') === 'y'); | |
| // 개인정보 동의 항목별 마지막 변경 일시(컬럼 공통). 이력 없으면 가입일(entryDt) 폴백 | |
| $privateAgreementDt = $history->getLastPrivateAgreementDateByMember((int) $memberNo); | |
| $memberEntryDt = $memberData['entryDt'] ?? ''; | |
| // 약관 동의 표시 행 조립 (개인정보 항목별/마케팅). 표시용 데이터 변환은 MemberUtil::buildPrivateAgreementRows | |
| $privateAgreements = [ | |
| ['title' => '개인정보 수집·이용', 'tooltipSeq' => '036', 'use' => is_array($memberData['privateApprovalOptionFl'] ?? null), 'informs' => $privateApprovalOption, 'flags' => $memberData['privateApprovalOptionFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateApprovalOptionFl'] ?? $memberEntryDt], | |
| ['title' => '개인정보 취급위탁', 'tooltipSeq' => '037', 'use' => is_array($memberData['privateConsignFl'] ?? null), 'informs' => $privateConsign, 'flags' => $memberData['privateConsignFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateConsignFl'] ?? $memberEntryDt], | |
| ['title' => '개인정보 제3자 제공', 'tooltipSeq' => '038', 'use' => is_array($memberData['privateOfferFl'] ?? null), 'informs' => $privateOffer, 'flags' => $memberData['privateOfferFl'] ?? [], 'denyWhenMissing' => false, 'agreementDt' => $privateAgreementDt['privateOfferFl'] ?? $memberEntryDt], | |
| ['title' => '마케팅 목적 개인정보 수집 및 이용 동의', 'tooltipSeq' => '039', 'use' => $privateMarketingMemberUse, 'informs' => $privateMarketingMember, 'flags' => $memberData['privateMarketingConsentOptionFl'] ?? '', 'denyWhenMissing' => true, 'agreementDt' => $privateAgreementDt['privateMarketingConsentOptionFl'] ?? $memberEntryDt], | |
| ]; | |
| $advertisingReceiveChannelUse = $buyerInform->getAdvertisingReceiveChannelUse($memberData['mallSno']); | |
| $advertisingReceive = [ | |
| 'email' => ['use' => $advertisingReceiveChannelUse['mail']], | |
| 'mobile' => ['use' => $advertisingReceiveChannelUse['sms']], | |
| ]; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의/거부일 (없으면 '-') | |
| $memberData['privateMktAgreementDt'] = $memberData['lastReceiveAgreementDt']['privateMkt'] ?? '-'; | |
| // 하이픈 제거 | |
| $memberData['fax'] = str_replace("-", "", $memberData['fax']); | |
| $this->setData('memberData', $memberData); | |
| $this->setData('mode', 'modify'); | |
| $this->setData('modeTxt', '회원수정'); | |
| $joinField = MemberUtil::getJoinField($memberData['mallSno']); | |
| $this->setData('joinField', $joinField); | |
| $this->setData('passwordPlaceholder', MemberUtil::buildPasswordPlaceholder($joinField)); | |
| $this->setData('htmlExtra', MemberUtil::makeExtraField($memberData)); | |
| $this->setData('privateMarketingMemberUse', $privateMarketingMemberUse); | |
| $this->setData('data', $memberData); | |
| $this->setData('checked', $checked); | |
| $this->setData('history', $memberHistory['data']); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateOffer', $privateOffer); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('privateMarketingMember', $privateMarketingMember); | |
| $this->setData('privateAgreementRows', MemberUtil::buildPrivateAgreementRows($privateAgreements)); | |
| $this->setData('advertisingReceive', $advertisingReceive); | |
| $this->setData('advertisingReceiveLines', MemberUtil::buildAdvertisingReceiveLines($advertisingReceive, $memberData)); | |
| $this->setData('groupCouponConditionManual', gd_policy('member.group')['couponConditionManual']); | |
| $this->setData('hidePasswordBlock', $hidePasswordBlock); | |
| $this->setData('certification', $certification); | |
변경 전JoinAgreementController.php
| $privateApprovalOption = $inform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION); | |
| $privateConsign = $inform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN); | |
| $privateOffer = $inform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER); | |
| $ipinConfig = gd_policy('member.ipin'); | |
| $authCellPhoneConfig = gd_get_auth_cellphone_info(); | |
| $memberJoinConfig = gd_policy('member.join'); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('privateOffer', $privateOffer); | |
| // debug($memberJoinConfig); | |
변경 후JoinAgreementController.php
| $privateApprovalOption = $inform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION); | |
| $privateConsign = $inform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN); | |
| $privateOffer = $inform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 / 광고성 수신 동의 | |
| $privateMarketingMember = $inform->getInformData(BuyerInformCode::PRIVATE_MARKETING_MEMBER); | |
| $advertisingReceive = $inform->getAdvertisingReceiveContentWithReplaceCode(); | |
| $advertisingReceiveChannelUse = $inform->getAdvertisingReceiveChannelUse(); | |
| $ipinConfig = gd_policy('member.ipin'); | |
| $authCellPhoneConfig = gd_get_auth_cellphone_info(); | |
| $memberJoinConfig = gd_policy('member.join'); | |
| $this->setData('privateApprovalOption', $privateApprovalOption); | |
| $this->setData('privateConsign', $privateConsign); | |
| $this->setData('privateOffer', $privateOffer); | |
| $this->setData('privateMarketingMember', $privateMarketingMember); | |
| $this->setData('advertisingReceive', $advertisingReceive); | |
| $this->setData('advertisingReceiveMailUse', $advertisingReceiveChannelUse['mail']); | |
| $this->setData('advertisingReceiveSmsUse', $advertisingReceiveChannelUse['sms']); | |
| $this->setData('isUseAdvertisingReceive', $inform->isUseAdvertisingReceive()); | |
| // debug($memberJoinConfig); | |
변경 전LoginPsController.php
| \DB::rollback(); | |
| $logger->info(__METHOD__ . ', ' . $e->getFile() . '[' . $e->getLine() . '], ' . $e->getMessage()); | |
| } | |
| } | |
| if($message){ | |
| throw new AlertRedirectException($message, 0, null, $returnUrl); | |
변경 후LoginPsController.php
| \DB::rollback(); | |
| $logger->info(__METHOD__ . ', ' . $e->getFile() . '[' . $e->getLine() . '], ' . $e->getMessage()); | |
| } | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 안내 (미동의 회원 로그인 시 계정당 1회, 확인 후 마이페이지 이동) | |
| // my_page.php는 진입 시 비밀번호 재확인을 요구하므로 게이트인 my_page_password.php로 직접 보낸다(이중 alert/리다이렉트 방지). | |
| if (empty($message) && $member->markPrivateMarketingConsentNoticeShown()) { | |
| $message = __('마케팅 이메일 및 모바일 메시지 수신을 위해 개인정보 수집 및 이용에 동의해 주세요.'); | |
| $returnUrl = '../mypage/my_page_password.php'; | |
| } | |
| } | |
| if($message){ | |
| throw new AlertRedirectException($message, 0, null, $returnUrl); | |
변경 전MyPageController.php
| $this->setData('privateApprovalOption', $inform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION)); | |
| $this->setData('privateOffer', $inform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER)); | |
| $this->setData('privateConsign', $inform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN)); | |
| $this->setData('snsConnection', json_encode($snsConnection)); | |
| $this->setData('usePaycoLogin', $paycoPolicy->usePaycoLogin()); | |
| $this->setData('useNaverLogin', $naverPolicy->useNaverLogin()); | |
변경 후MyPageController.php
| $this->setData('privateApprovalOption', $inform->getInformDataArray(BuyerInformCode::PRIVATE_APPROVAL_OPTION)); | |
| $this->setData('privateOffer', $inform->getInformDataArray(BuyerInformCode::PRIVATE_OFFER)); | |
| $this->setData('privateConsign', $inform->getInformDataArray(BuyerInformCode::PRIVATE_CONSIGN)); | |
| $this->setData('privateMktApprovalOption', $inform->getInformDataArray(BuyerInformCode::PRIVATE_MARKETING_MEMBER)); | |
| $this->setData('advertisingReceive', $inform->getAdvertisingReceiveContentWithReplaceCode((int)$mallSno)); | |
| // 광고성 수신 동의 채널(이메일/모바일) 노출 여부 | |
| $advertisingReceiveChannelUse = $inform->getAdvertisingReceiveChannelUse((int)$mallSno); | |
| $this->setData('advertisingReceiveMailUse', $advertisingReceiveChannelUse['mail']); | |
| $this->setData('advertisingReceiveSmsUse', $advertisingReceiveChannelUse['sms']); | |
| // 광고성 수신 동의 블록 노출 = 채널 하나라도 사용 (es_buyerInform modeFl 아님) | |
| $this->setData('isUseAdvertisingReceive', $inform->isUseAdvertisingReceive((int)$mallSno)); | |
| $this->setData('snsConnection', json_encode($snsConnection)); | |
| $this->setData('usePaycoLogin', $paycoPolicy->usePaycoLogin()); | |
| $this->setData('useNaverLogin', $naverPolicy->useNaverLogin()); | |
변경 전AgreementController.php
| case BuyerInformCode::PRIVATE_APPROVAL: | |
| $terms = $inform->getInformData(BuyerInformCode::PRIVATE_APPROVAL); | |
| break; | |
| case BuyerInformCode::BASE_PRIVATE: | |
| $terms = $inform->getPrivateWithReplaceCode(BuyerInformCode::BASE_PRIVATE); | |
| break; | |
변경 후AgreementController.php
| case BuyerInformCode::PRIVATE_APPROVAL: | |
| $terms = $inform->getInformData(BuyerInformCode::PRIVATE_APPROVAL); | |
| break; | |
| case BuyerInformCode::PRIVATE_MARKETING_MEMBER: | |
| $terms = $inform->getInformData(BuyerInformCode::PRIVATE_MARKETING_MEMBER); | |
| break; | |
| case BuyerInformCode::ADVERTISING_RECEIVE: | |
| $terms = $inform->getAdvertisingReceiveContentWithReplaceCode(); | |
| break; | |
| case BuyerInformCode::BASE_PRIVATE: | |
| $terms = $inform->getPrivateWithReplaceCode(BuyerInformCode::BASE_PRIVATE); | |
| break; | |
변경 전join_agreement.html
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <div class="important_check_box"> | |
| <strong class="important_check dn">{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</strong> | |
| </div> | |
| $('.js_terms_view :checkbox', $formTerms).change(function (e) { | |
| $('strong.important_check').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.js_terms_view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| if (isTermsAgreeSelect) { | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| }); | |
| </script> | |
| { # footer } | |
변경 후join_agreement.html
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <!-- {? privateMarketingMember['modeFl']=='y'} --> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree6" name=""/> | |
| <label class="check_s" for="termsAgree6"><strong class="choice">({=__('선택')})</strong> {=__('마케팅 목적 개인정보 수집 및 이용 동의')} </label> | |
| <span><a href="../service/agreement.php?code={privateMarketingMember['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}" border="0" cellpadding="0" cellspacing="0"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(privateMarketingMember['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"/> | |
| <label class="check_s" for="privateMktApprovalOption">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td>{=nl2br(privateMarketingMember['content'])}</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <!-- {? isUseAdvertisingReceive} --> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree7" name=""/> | |
| <label class="check_s" for="termsAgree7"><strong class="choice">({=__('선택')})</strong> {=__('광고성 수신 동의')} </label> | |
| <span><a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table summary="{=__('광고성 수신 동의 내용입니다.')}" border="0" cellpadding="0" cellspacing="0"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveAll" name=""/> | |
| <label class="check_s" for="advertisingReceiveAll">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td>{=nl2br(advertisingReceive['content'])}</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!-- {? advertisingReceiveMailUse=='y'} --> | |
| <div class="form_element"> | |
| <input type="checkbox" id="maillingFl" name="maillingFl" class="js_advertising_channel"/> | |
| <label class="check_s" for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </div> | |
| <!-- {/} --> | |
| <!-- {? advertisingReceiveSmsUse=='y'} --> | |
| <div class="form_element"> | |
| <input type="checkbox" id="smsFl" name="smsFl" class="js_advertising_channel"/> | |
| <label class="check_s" for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </div> | |
| <!-- {/} --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <div class="important_check_box"> | |
| <strong class="important_check dn">{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</strong> | |
| </div> | |
| $('.js_terms_view :checkbox', $formTerms).change(function (e) { | |
| $('strong.important_check').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.js_terms_view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| if (isTermsAgreeSelect) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.js_terms_view .agreement_choice_box :checkbox', function () { | |
| const $termsView = $(this).closest('.js_terms_view'); | |
| const $header = $termsView.children('.form_element').children(':checkbox'); | |
| const $subs = $termsView.find('.agreement_choice_box :checkbox'); | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| </script> | |
| { # footer } | |
변경 전_join_view.html
| </select> | |
| </div> | |
| <div class="member_warning js_email"></div> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="maillingFl" name="maillingFl" value="y" {? data.maillingFl == 'y'}checked="checked"{/}/> | |
| <label for="maillingFl" class="check_s {? data.maillingFl == 'y'}on{/}">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="smsFl" name="smsFl" value="y" {? data.smsFl == 'y'}checked="checked"{/}/> | |
| <label for="smsFl" class="check_s {? data.smsFl == 'y'}on{/}">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
변경 후_join_view.html
| </select> | |
| </div> | |
| <div class="member_warning js_email"></div> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
변경 전_join_view_other.html
| <!--{/}--> | |
| <!-- N : 약관동의 시작 --> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y'}--> | |
| <div class="join_agreement_cont"> | |
| <h3>{=__('약관동의현황')}</h3> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateOffer modeFl end}--> | |
| </div> | |
| <!-- //join_agreement_cont --> | |
| <!--{ / }--> | |
변경 후_join_view_other.html
| <!--{/}--> | |
| <!-- N : 약관동의 시작 --> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y' || privateMktApprovalOption[0]['modeFl']=='y' || isUseAdvertisingReceive}--> | |
| <div class="join_agreement_cont"> | |
| <h3>{=__('약관동의현황')}</h3> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="join_agreement_box"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree6"/> | |
| <label for="termsAgree6" class="check_s"><strong class="choice">({=__('선택')})</strong> {=__('마케팅 목적 개인정보 수집 및 이용 동의')} </label> | |
| <span><a href="../service/agreement.php?code={privateMktApprovalOption[0]['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <!--{@ privateMktApprovalOption}--> | |
| <div class="agreement_choice_box"> | |
| <table border="0" cellpadding="0" cellspacing="0" summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(.informNm)}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="privateMarketingConsentOptionFl" class="check_s <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->on<!--{/}-->">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="agreement_scroll"> | |
| {=nl2br(.content)} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!--{/ // privateMktApprovalOption loop end}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree7"/> | |
| <label for="termsAgree7" class="check_s"><strong class="choice">({=__('선택')})</strong> {=__('광고성 수신 동의')} </label> | |
| <span><a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table border="0" cellpadding="0" cellspacing="0" summary="{=__('광고성 수신 동의 내용입니다.')}"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveAll" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveAll" class="check_s <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->on<!--{/}-->">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="agreement_scroll"> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveMail" name="maillingFl" value="y" class="js_advertising_channel" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveMail" class="check_s <!--{? data['maillingFl'] == 'y'}-->on<!--{/}-->">{=__('이메일 수신 동의')}</label> | |
| </div> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveSms" name="smsFl" value="y" class="js_advertising_channel" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveSms" class="check_s <!--{? data['smsFl'] == 'y'}-->on<!--{/}-->">{=__('모바일 메시지 수신 동의')}</label> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!-- //agreement_choice_box --> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| </div> | |
| <!-- //join_agreement_cont --> | |
| <!--{ / }--> | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.join_agreement_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.join_agreement_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7', $formJoin).prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formJoin).length > 0; | |
| const allChannelChecked = $('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0; | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formJoin).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $formJoin.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) | |
| $formJoin.on('change', '.join_agreement_box .agreement_choice_box :checkbox', function () { | |
| const $box = $(this).closest('.join_agreement_box'); | |
| const $header = $box.children('.form_element').children(':checkbox'); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| const $subs = $box.find('.agreement_choice_box :checkbox'); | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('.join_agreement_box', $formJoin).each(function () { | |
| const $box = $(this); | |
| const $header = $box.children('.form_element').children(':checkbox'); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| const $subs = $box.find('.agreement_choice_box :checkbox'); | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $header.prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전join_agreement.html
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <div class="important_check_box"> | |
| <strong class="important_check dn">{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</strong> | |
| </div> | |
| $('.js_terms_view :checkbox', $formTerms).change(function (e) { | |
| $('strong.important_check').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.js_terms_view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| if (isTermsAgreeSelect) { | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| }); | |
| </script> | |
| { # footer } | |
변경 후join_agreement.html
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <!-- {? privateMarketingMember['modeFl']=='y'} --> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree6" name=""/> | |
| <label class="check_s" for="termsAgree6"><strong class="choice">({=__('선택')})</strong> {=__('마케팅 목적 개인정보 수집 및 이용 동의')} </label> | |
| <span><a href="../service/agreement.php?code={privateMarketingMember['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}" border="0" cellpadding="0" cellspacing="0"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(privateMarketingMember['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"/> | |
| <label class="check_s" for="privateMktApprovalOption">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td>{=nl2br(privateMarketingMember['content'])}</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <!-- {? isUseAdvertisingReceive} --> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree7" name=""/> | |
| <label class="check_s" for="termsAgree7"><strong class="choice">({=__('선택')})</strong> {=__('광고성 수신 동의')} </label> | |
| <span><a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table summary="{=__('광고성 수신 동의 내용입니다.')}" border="0" cellpadding="0" cellspacing="0"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveAll" name=""/> | |
| <label class="check_s" for="advertisingReceiveAll">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td>{=nl2br(advertisingReceive['content'])}</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!-- {? advertisingReceiveMailUse=='y'} --> | |
| <div class="form_element"> | |
| <input type="checkbox" id="maillingFl" name="maillingFl" class="js_advertising_channel"/> | |
| <label class="check_s" for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </div> | |
| <!-- {/} --> | |
| <!-- {? advertisingReceiveSmsUse=='y'} --> | |
| <div class="form_element"> | |
| <input type="checkbox" id="smsFl" name="smsFl" class="js_advertising_channel"/> | |
| <label class="check_s" for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </div> | |
| <!-- {/} --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- //join_agreement_box --> | |
| <div class="important_check_box"> | |
| <strong class="important_check dn">{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</strong> | |
| </div> | |
| $('.js_terms_view :checkbox', $formTerms).change(function (e) { | |
| $('strong.important_check').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.js_terms_view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| if (isTermsAgreeSelect) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.js_terms_view .agreement_choice_box :checkbox', function () { | |
| const $termsView = $(this).closest('.js_terms_view'); | |
| const $header = $termsView.children('.form_element').children(':checkbox'); | |
| const $subs = $termsView.find('.agreement_choice_box :checkbox'); | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| </script> | |
| { # footer } | |
변경 전_join_view.html
| </select> | |
| </div> | |
| <div class="member_warning js_email"></div> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="maillingFl" name="maillingFl" value="y" {? data.maillingFl == 'y'}checked="checked"{/}/> | |
| <label for="maillingFl" class="check_s {? data.maillingFl == 'y'}on{/}">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="smsFl" name="smsFl" value="y" {? data.smsFl == 'y'}checked="checked"{/}/> | |
| <label for="smsFl" class="check_s {? data.smsFl == 'y'}on{/}">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
변경 후_join_view.html
| </select> | |
| </div> | |
| <div class="member_warning js_email"></div> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </td> | |
| </tr> | |
| <!--{/}--> | |
변경 전_join_view_other.html
| <!--{/}--> | |
| <!-- N : 약관동의 시작 --> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y'}--> | |
| <div class="join_agreement_cont"> | |
| <h3>{=__('약관동의현황')}</h3> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateOffer modeFl end}--> | |
| </div> | |
| <!-- //join_agreement_cont --> | |
| <!--{ / }--> | |
변경 후_join_view_other.html
| <!--{/}--> | |
| <!-- N : 약관동의 시작 --> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y' || privateMktApprovalOption[0]['modeFl']=='y' || isUseAdvertisingReceive}--> | |
| <div class="join_agreement_cont"> | |
| <h3>{=__('약관동의현황')}</h3> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="join_agreement_box"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree6"/> | |
| <label for="termsAgree6" class="check_s"><strong class="choice">({=__('선택')})</strong> {=__('마케팅 목적 개인정보 수집 및 이용 동의')} </label> | |
| <span><a href="../service/agreement.php?code={privateMktApprovalOption[0]['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <!--{@ privateMktApprovalOption}--> | |
| <div class="agreement_choice_box"> | |
| <table border="0" cellpadding="0" cellspacing="0" summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(.informNm)}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="privateMarketingConsentOptionFl" class="check_s <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->on<!--{/}-->">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="agreement_scroll"> | |
| {=nl2br(.content)} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!--{/ // privateMktApprovalOption loop end}--> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="join_agreement_box js_terms_view"> | |
| <div class="form_element"> | |
| <input type="checkbox" id="termsAgree7"/> | |
| <label for="termsAgree7" class="check_s"><strong class="choice">({=__('선택')})</strong> {=__('광고성 수신 동의')} </label> | |
| <span><a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a></span> | |
| </div> | |
| <div class="agreement_choice_box"> | |
| <table border="0" cellpadding="0" cellspacing="0" summary="{=__('광고성 수신 동의 내용입니다.')}"> | |
| <colgroup> | |
| <col width="10px"> | |
| <col width="300px"> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th>{=__('선택')}</th> | |
| <th>{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveAll" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveAll" class="check_s <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->on<!--{/}-->">{=__('선택')}</label> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="agreement_scroll"> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveMail" name="maillingFl" value="y" class="js_advertising_channel" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveMail" class="check_s <!--{? data['maillingFl'] == 'y'}-->on<!--{/}-->">{=__('이메일 수신 동의')}</label> | |
| </div> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <div class="form_element"> | |
| <input type="checkbox" id="advertisingReceiveSms" name="smsFl" value="y" class="js_advertising_channel" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveSms" class="check_s <!--{? data['smsFl'] == 'y'}-->on<!--{/}-->">{=__('모바일 메시지 수신 동의')}</label> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!-- //agreement_choice_box --> | |
| </div> | |
| <!-- //join_agreement_box --> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| </div> | |
| <!-- //join_agreement_cont --> | |
| <!--{ / }--> | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.join_agreement_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.join_agreement_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7', $formJoin).prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formJoin).length > 0; | |
| const allChannelChecked = $('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0; | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formJoin).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $formJoin.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) | |
| $formJoin.on('change', '.join_agreement_box .agreement_choice_box :checkbox', function () { | |
| const $box = $(this).closest('.join_agreement_box'); | |
| const $header = $box.children('.form_element').children(':checkbox'); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| const $subs = $box.find('.agreement_choice_box :checkbox'); | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('.join_agreement_box', $formJoin).each(function () { | |
| const $box = $(this); | |
| const $header = $box.children('.form_element').children(':checkbox'); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| const $subs = $box.find('.agreement_choice_box :checkbox'); | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $header.prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전join_agreement.html
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| $('.terms-view :checkbox', $formTerms).change(function (e) { | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| }); | |
| </script> | |
| { # footer } | |
변경 후join_agreement.html
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- {? privateMarketingMember['modeFl']=='y'} --> | |
| <div class="terms-view"> | |
| <p> | |
| <input type="checkbox" class="checkbox" id="termsAgree6" name=""> | |
| <label for="termsAgree6"> | |
| <span class="option"><strong>({=__('선택')})</strong></span> | |
| {=__('마케팅 목적 개인정보 수집 및 이용 동의')} | |
| </label> | |
| <a href="../service/agreement.php?code={privateMarketingMember['informCd']}" target="_blank">{=__('전체보기')}</a> | |
| </p> | |
| <div class="consignment-box"> | |
| <table summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}" class="" cellspacing="0" border="1"> | |
| <colgroup> | |
| <col width="79px"> | |
| <col> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th scope="col">{=__('선택')}</th> | |
| <th scope="col">{=nl2br(privateMarketingMember['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"> | |
| <label for="privateMktApprovalOption">{=__('선택')}</label> | |
| </span> | |
| </td> | |
| <td> | |
| <div> | |
| {=nl2br(privateMarketingMember['content'])} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <!-- {? isUseAdvertisingReceive} --> | |
| <div class="terms-view"> | |
| <p> | |
| <input type="checkbox" class="checkbox" id="termsAgree7" name=""> | |
| <label for="termsAgree7"> | |
| <span class="option"><strong>({=__('선택')})</strong></span> | |
| {=__('광고성 수신 동의')} | |
| </label> | |
| <a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a> | |
| </p> | |
| <div class="consignment-box"> | |
| <table summary="{=__('광고성 수신 동의 내용입니다.')}" class="" cellspacing="0" border="1"> | |
| <colgroup> | |
| <col width="79px"> | |
| <col> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th scope="col">{=__('선택')}</th> | |
| <th scope="col">{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox" id="advertisingReceiveAll" name=""> | |
| <label for="advertisingReceiveAll">{=__('선택')}</label> | |
| </span> | |
| </td> | |
| <td> | |
| <div> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; gap:8px; margin:10px;"> | |
| <!-- {? advertisingReceiveMailUse=='y'} --> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox js_advertising_channel" id="maillingFl" name="maillingFl"> | |
| <label for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!-- {/} --> | |
| <!-- {? advertisingReceiveSmsUse=='y'} --> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox js_advertising_channel" id="smsFl" name="smsFl"> | |
| <label for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!-- {/} --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- {/} --> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| $('.terms-view :checkbox', $formTerms).change(function (e) { | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| } | |
| }); | |
| } | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.terms-view .consignment-box :checkbox', function () { | |
| const $termsView = $(this).closest('.terms-view'); | |
| const $header = $termsView.children('p').children(':checkbox'); | |
| const $subs = $termsView.find('.consignment-box :checkbox'); | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| </script> | |
| { # footer } | |
변경 전_join_view.html
| </select> | |
| </div> | |
| </div> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="form-element"> | |
| <input type="checkbox" class="checkbox" id="maillingFl" name="maillingFl" value="y" {? data.maillingFl == 'y'}checked="checked"{/}> | |
| <label for="maillingFl" class="{? data.maillingFl == 'y'}on{/}">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--><!--{? joinField.cellPhone.use == 'y'}--> | |
| </button> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="form-element"> | |
| <input type="checkbox" class="checkbox" id="smsFl" name="smsFl" value="y" {? data.smsFl == 'y'}checked="checked"{/}> | |
| <label for="smsFl" class="{? data.smsFl == 'y'}on{/}">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </div> | |
| <!--{/}--> | |
| </td> | |
| </tr> | |
| <!--{/}--><!--{? joinField.phone.use == 'y'}--> | |
변경 후_join_view.html
| </select> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <!--{/}--><!--{? joinField.cellPhone.use == 'y'}--> | |
| </button> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </td> | |
| </tr> | |
| <!--{/}--><!--{? joinField.phone.use == 'y'}--> | |
변경 전_join_view_other.html
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{/ // isMyPage end}--> | |
변경 후_join_view_other.html
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="terms-view"> | |
| <p> | |
| <input type="checkbox" class="checkbox" id="termsAgree6" name=""> | |
| <label for="termsAgree6"> | |
| <span class="option"> | |
| <strong>({=__('선택')})</strong> | |
| </span> | |
| {=__('마케팅 목적 개인정보 수집 및 이용 동의')} | |
| </label> | |
| <a href="../service/agreement.php?code={privateMktApprovalOption[0]['informCd']}" target="_blank">{=__('전체보기')}</a> | |
| </p> | |
| <div class="consignment-box"> | |
| <!--{@ privateMktApprovalOption}--> | |
| <table summary="{=__('마케팅 목적 개인정보 수집 및 이용 동의 내용입니다.')}" class="" cellspacing="0" border="1"> | |
| <colgroup> | |
| <col width="79px"> | |
| <col> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th scope="col">{=__('선택')}</th> | |
| <th scope="col">{=nl2br(.informNm)}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="<!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->on<!--{/}-->" for="privateMarketingConsentOptionFl">{=__('선택')}</label> | |
| </span> | |
| </td> | |
| <td> | |
| <div> | |
| {=nl2br(.content)} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <!--{/ // privateMktApprovalOption loop end}--> | |
| </div> | |
| </div> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="terms-view js_terms_view"> | |
| <p> | |
| <input type="checkbox" class="checkbox" id="termsAgree7" name=""> | |
| <label for="termsAgree7"> | |
| <span class="option"> | |
| <strong>({=__('선택')})</strong> | |
| </span> | |
| {=__('광고성 수신 동의')} | |
| </label> | |
| <a href="../service/agreement.php?code={advertisingReceive['informCd']}" target="_blank">{=__('전체보기')}</a> | |
| </p> | |
| <div class="consignment-box"> | |
| <table summary="{=__('광고성 수신 동의 내용입니다.')}" class="" cellspacing="0" border="1"> | |
| <colgroup> | |
| <col width="79px"> | |
| <col> | |
| </colgroup> | |
| <thead> | |
| <tr> | |
| <th scope="col">{=__('선택')}</th> | |
| <th scope="col">{=nl2br(advertisingReceive['informNm'])}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox" id="advertisingReceiveAll" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="<!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveAll">{=__('선택')}</label> | |
| </span> | |
| </td> | |
| <td> | |
| <div> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; gap:8px; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox js_advertising_channel" id="advertisingReceiveMail" name="maillingFl" value="y" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="<!--{? data['maillingFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveMail">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <span class="form-element"> | |
| <input type="checkbox" class="checkbox js_advertising_channel" id="advertisingReceiveSms" name="smsFl" value="y" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="<!--{? data['smsFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveSms">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| <!--{/ // isMyPage end}--> | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7', $formJoin).prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formJoin).length > 0; | |
| const allChannelChecked = $('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0; | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formJoin).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $formJoin.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) | |
| // - story_g 는 약관 그룹 마크업이 .terms-view / .consignment-box 구조 (moment·mygreek 의 .join_agreement_box 아님) | |
| $formJoin.on('change', '.terms-view .consignment-box :checkbox', function () { | |
| const $box = $(this).closest('.terms-view'); | |
| const $subs = $box.find('.consignment-box :checkbox'); | |
| const $header = $box.find(':checkbox').not($subs); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| const allChecked = $subs.length > 0 && $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('.terms-view', $formJoin).each(function () { | |
| const $box = $(this); | |
| const $subs = $box.find('.consignment-box :checkbox'); | |
| const $header = $box.find(':checkbox').not($subs); | |
| // 광고성 수신 동의(termsAgree7)는 채널 1개 이상 선택 의미라 전체 선택 동기화에서 제외 | |
| if ($header.attr('id') === 'termsAgree7') { | |
| return; | |
| } | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $header.prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전join_agreement.html
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
| } | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| }); | |
| /** | |
변경 후join_agreement.html
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateMarketingMember['modeFl']=='y'}--> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree6"/> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"/> | |
| <label for="privateMktApprovalOption">{=nl2br(privateMarketingMember['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{privateMarketingMember['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(privateMarketingMember['content'])}</div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!-- //privacy_big_box --> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree7"/> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="advertisingReceiveAll"/> | |
| <label for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(advertisingReceive['content'])}</div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!-- //privacy_big_box --> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse=='y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="maillingFl" name="maillingFl"/> | |
| <label for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse=='y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="smsFl" name="smsFl"/> | |
| <label for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button:not(.js_agreement_view)').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
| } | |
| }); | |
| // 약관 전문 새창 열기 (전체보기) | |
| $('.js_agreement_view').on('click', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.privacy_box :checkbox', function () { | |
| const $box = $(this).closest('.privacy_box'); | |
| const $header = $box.children('dl').find(':checkbox'); | |
| const $subs = $box.find(':checkbox').not($header); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| /** | |
변경 전_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="description"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="maillingFl" class="ignore" name="maillingFl" value="y" {? data.maillingFl=='y'}checked="checked"{/}/> | |
| <label for="maillingFl">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| <!--{/}--> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <div class="description"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="ignore" id="smsFl" name="smsFl" value="y" {? data.smsFl=='y'}checked="checked"{/}/> | |
| <label for="smsFl">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{/}--> | |
| <!--{? joinField.phone.use == 'y'}--> | |
| <div class="input_wrap"> | |
변경 후_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? joinField.phone.use == 'y'}--> | |
| <div class="input_wrap"> | |
변경 전_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y'}--> | |
| <p class="tit">{=__('약관동의현황')}</p> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
변경 후_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y' || privateMktApprovalOption[0]['modeFl']=='y' || isUseAdvertisingReceive}--> | |
| <p class="tit">{=__('약관동의현황')}</p> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree6" name=""/> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <!--{@ privateMktApprovalOption}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="privateMarketingConsentOptionFl">{=nl2br(.informNm)}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{.informCd}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(.content)}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree7" name=""/> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveAll" name="" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(advertisingReceive['content'])}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveMail" name="maillingFl" value="y" class="js_advertising_channel" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveMail">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveSms" name="smsFl" value="y" class="js_advertising_channel" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveSms">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.js_agreement_view').on('click', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| $('.privacy_box dd button:not(.js_agreement_view)').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7', $formJoin).prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formJoin).length > 0; | |
| const allChannelChecked = $('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0; | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formJoin).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $formJoin.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) — 중첩 privacy_box 대응: 헤더 기준으로 그룹 판정 | |
| $formJoin.on('change', '.privacy_box :checkbox', function () { | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6', $formJoin).each(function () { | |
| const $header = $(this); | |
| const $subs = $header.closest('.privacy_box').find(':checkbox').not($header); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6', $formJoin).each(function () { | |
| const $subs = $(this).closest('.privacy_box').find(':checkbox').not(this); | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $(this).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전join_agreement.html
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
| } | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| }); | |
| /** | |
변경 후join_agreement.html
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateMarketingMember['modeFl']=='y'}--> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree6"/> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"/> | |
| <label for="privateMktApprovalOption">{=nl2br(privateMarketingMember['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{privateMarketingMember['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(privateMarketingMember['content'])}</div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!-- //privacy_big_box --> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree7"/> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="advertisingReceiveAll"/> | |
| <label for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(advertisingReceive['content'])}</div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!-- //privacy_big_box --> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse=='y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="maillingFl" name="maillingFl"/> | |
| <label for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse=='y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="smsFl" name="smsFl"/> | |
| <label for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!-- //privacy_content --> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| /* | |
| * 14세 동의 항목 체크박스 이벤트 | |
| */ | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button:not(.js_agreement_view)').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
| } | |
| }); | |
| // 약관 전문 새창 열기 (전체보기) | |
| $('.js_agreement_view').on('click', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.privacy_box :checkbox', function () { | |
| const $box = $(this).closest('.privacy_box'); | |
| const $header = $box.children('dl').find(':checkbox'); | |
| const $subs = $box.find(':checkbox').not($header); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| /** | |
변경 전_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="description"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="maillingFl" class="ignore" name="maillingFl" value="y" {? data.maillingFl=='y'}checked="checked"{/}/> | |
| <label for="maillingFl">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| <!--{/}--> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <div class="description"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="ignore" id="smsFl" name="smsFl" value="y" {? data.smsFl=='y'}checked="checked"{/}/> | |
| <label for="smsFl">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{/}--> | |
| <!--{? joinField.phone.use == 'y'}--> | |
| <div class="input_wrap"> | |
변경 후_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? joinField.phone.use == 'y'}--> | |
| <div class="input_wrap"> | |
변경 전_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y'}--> | |
| <p class="tit">{=__('약관동의현황')}</p> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.privacy_box dd button').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
변경 후_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y' || privateMktApprovalOption[0]['modeFl']=='y' || isUseAdvertisingReceive}--> | |
| <p class="tit">{=__('약관동의현황')}</p> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree6" name=""/> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <!--{@ privateMktApprovalOption}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="privateMarketingConsentOptionFl">{=nl2br(.informNm)}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{.informCd}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(.content)}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="termsAgree7" name=""/> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button">{=__('내용보기')} ▼</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div class="privacy_big_box"> | |
| <div class="privacy_box"> | |
| <dl> | |
| <dt> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveAll" name="" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| </dt> | |
| <dd><button type="button" class="js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button></dd> | |
| </dl> | |
| <div class="privacy_content"> | |
| <div>{=nl2br(advertisingReceive['content'])}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveMail" name="maillingFl" value="y" class="js_advertising_channel" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveMail">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <span class="inp_chk"> | |
| <input type="checkbox" id="advertisingReceiveSms" name="smsFl" value="y" class="js_advertising_channel" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->/> | |
| <label for="advertisingReceiveSms">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function() { | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| /* | |
| * 약관 내용보기 이벤트 | |
| */ | |
| $('.js_agreement_view').on('click', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| $('.privacy_box dd button:not(.js_agreement_view)').on({ | |
| 'click':function(){ | |
| var privacy_dp = $(this).parent().parent().parent().find('> .privacy_content').css('display'); | |
| if(privacy_dp == 'none'){ | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy_box'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formJoin).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7', $formJoin).prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formJoin.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formJoin).length > 0; | |
| const allChannelChecked = $('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0; | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formJoin).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formJoin).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formJoin.on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formJoin).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $formJoin.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) — 중첩 privacy_box 대응: 헤더 기준으로 그룹 판정 | |
| $formJoin.on('change', '.privacy_box :checkbox', function () { | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6', $formJoin).each(function () { | |
| const $header = $(this); | |
| const $subs = $header.closest('.privacy_box').find(':checkbox').not($header); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6', $formJoin).each(function () { | |
| const $subs = $(this).closest('.privacy_box').find(':checkbox').not(this); | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $(this).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel', $formJoin).length > 0 | |
| && $('.js_advertising_channel:not(:checked)', $formJoin).length === 0) { | |
| $('#termsAgree7', $formJoin).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| gd_select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전join_agreement.html
| </div> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| $(document).ready(function () { | |
| var body = $('body'), $formTerms = $('#formTerms'); | |
| $('#btnNextStep').click(function () { | |
| var pass = true; | |
| /* | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy-item'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| }); | |
| /** | |
| * 아이폰+페이스북앱에서 location.href로 페이지 이동으로 처리시 | |
변경 후join_agreement.html
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateMarketingMember['modeFl']=='y'}--> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="termsAgree6" name=""> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset toggle-switch">{=__('내용보기')} ▼</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="privateMktApprovalOption" name="privateMarketingConsentOptionFl"> | |
| <label for="privateMktApprovalOption">{=nl2br(privateMarketingMember['informNm'])}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset js_agreement_view" data-code="{privateMarketingMember['informCd']}">{=__('전체보기')}</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| {=nl2br(privateMarketingMember['content'])} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="termsAgree7" name=""> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset toggle-switch">{=__('내용보기')} ▼</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="advertisingReceiveAll" name=""> | |
| <label for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </div> | |
| <div class="js_advertising_channel_box"> | |
| <!--{? advertisingReceiveMailUse=='y'}--> | |
| <div class="privacy-item"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="maillingFl" name="maillingFl"> | |
| <label for="maillingFl">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse=='y'}--> | |
| <div class="privacy-item"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="smsFl" name="smsFl"> | |
| <label for="smsFl">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <p class="msg dn"> | |
| <span>{=__('이용약관과 개인정보 수집 및 이용에 대한 안내 모두 동의해주세요.')}</span> | |
| </p> | |
| $(document).ready(function () { | |
| var body = $('body'), $formTerms = $('#formTerms'); | |
| // 약관 전문 새창 열기 (전체보기) | |
| body.on('click', '.js_agreement_view', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| $('#btnNextStep').click(function () { | |
| var pass = true; | |
| /* | |
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy-item'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMktApprovalOption', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7', $formTerms).length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel', $formTerms).prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $formTerms.on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $formTerms.on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel', $formTerms).prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } else { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked', $formTerms).length > 0; | |
| $('#advertisingReceiveAll', $formTerms).prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#privateMktApprovalOption', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6', $formTerms).prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| $formTerms.on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| window.addEventListener('message', function (e) { | |
| if (e.origin === "{=authDreamUrl}") { | |
| $('#layerSearch').remove(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더(termsAgree3~7)도 선택 (하나라도 해제 시 해제) | |
| $formTerms.on('change', '.privacy-item.toggle-item .privacy-body :checkbox', function () { | |
| const $group = $(this).closest('.privacy-body').closest('.privacy-item.toggle-item'); | |
| const $header = $group.children('.privacy-head').find(':checkbox'); | |
| const $subs = $group.children('.privacy-body').find(':checkbox'); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| /* | |
| * 전체 동의 역동기화 — 하위 체크박스가 모두 선택되면 전체 동의도 선택 (하나라도 해제되면 해제) | |
| */ | |
| const syncAllAgree = function () { | |
| const $targets = $(':checkbox', $formTerms).not('#allAgree').not('#termsAgree'); | |
| const allChecked = $targets.length > 0 && $targets.not(':checked').length === 0; | |
| $('#allAgree', $formTerms).prop('checked', allChecked) | |
| .siblings('label').toggleClass('on', allChecked); | |
| }; | |
| $formTerms.on('change', ':checkbox', function (e) { | |
| if (e.target.id === 'allAgree' || e.target.id === 'termsAgree') { | |
| return; | |
| } | |
| syncAllAgree(); | |
| }); | |
| }); | |
| /** | |
| * 아이폰+페이스북앱에서 location.href로 페이지 이동으로 처리시 | |
변경 전_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <!--{? joinField.maillingFl.use === 'y'}--> | |
| <div class="description chk"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="checkbox sp" id="maillingFl" name="maillingFl" value="y" {? data.maillingFl== | |
| 'y'}checked="checked"{/}> | |
| <label for="maillingFl">{=__('정보/이벤트 메일 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| <!--{/}--> | |
| <div class="description_wrap"> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| <!--{? joinField.smsFl.use === 'y'}--> | |
| <div class="description chk"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="checkbox sp" id="smsFl" name="smsFl" value="y" {? data.smsFl== | |
| 'y'}checked="checked"{/}> | |
| <label for="smsFl">{=__('정보/이벤트 SMS 수신에 동의합니다.')}</label> | |
| </span> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!--{/}--><!--{? joinField.phone.use == 'y'}--> | |
변경 후_join_view.html
| <div class="input_wrap"> | |
| <div class="input_title"></div> | |
| <div class="input_content"> | |
| <div class="description_wrap"> | |
| <div class="description">※ {=__('아이디 비밀번호 찾기에 활용 되므로 정확하게 입력해 주세요')}</div> | |
| </div> | |
| </div> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| <!--{/}--><!--{? joinField.phone.use == 'y'}--> | |
변경 전_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y'}--> | |
| <div class="account_title"> | |
| <b class="title">{=__('약관동의현황')}</b> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function () { | |
| e.preventDefault(); | |
| $('p.msg').addClass('hidden'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy-item'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| <!--{ ? useAppleLogin }--> | |
| $("#apple_btn").on("click", startClicked); | |
| function startClicked(){ | |
변경 후_join_view_other.html
| <!--{/}--> | |
| </div> | |
| <!--{/}--> | |
| <!--{? privateApprovalOption[0]['modeFl'] == 'y' || privateConsign[0]['modeFl']=='y' || privateOffer[0]['modeFl']=='y' || privateMktApprovalOption[0]['modeFl']=='y' || isUseAdvertisingReceive}--> | |
| <div class="account_title"> | |
| <b class="title">{=__('약관동의현황')}</b> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // privateOffer modeFl end}--> | |
| <!--{? privateMktApprovalOption[0]['modeFl'] == 'y'}--> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="termsAgree6" name=""> | |
| <label for="termsAgree6">({=__('선택')}) {=__('마케팅 목적 개인정보 수집 및 이용 동의')}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset toggle-switch">{=__('내용보기')} ▼</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| <!--{@ privateMktApprovalOption}--> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="privateMarketingConsentOptionFl" name="privateMarketingConsentOptionFl" value="y" <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="single <!--{? data['privateMarketingConsentOptionFl'] == 'y'}-->on<!--{/}-->" for="privateMarketingConsentOptionFl">{=nl2br(.informNm)}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset js_agreement_view" data-code="{.informCd}">{=__('전체보기')}</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| {=nl2br(.content)} | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| <!--{/ // privateMktApprovalOption modeFl end}--> | |
| <!--{? isUseAdvertisingReceive}--> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="termsAgree7" name=""> | |
| <label for="termsAgree7">({=__('선택')}) {=__('광고성 수신 동의')}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset toggle-switch">{=__('내용보기')} ▼</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| <div class="privacy-item toggle-item toggle-open"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp" id="advertisingReceiveAll" <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="single <!--{? data['maillingFl'] == 'y' || data['smsFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveAll">{=nl2br(advertisingReceive['informNm'])}</label> | |
| </span> | |
| <div class="option"> | |
| <button type="button" class="btn-reset js_agreement_view" data-code="{advertisingReceive['informCd']}">{=__('전체보기')}</button> | |
| </div> | |
| </div> | |
| <div class="privacy-body"> | |
| {=nl2br(advertisingReceive['content'])} | |
| </div> | |
| </div> | |
| <div class="js_advertising_channel_box" style="display:flex; flex-direction:column; align-items:flex-start; margin:10px;"> | |
| <!--{? advertisingReceiveMailUse == 'y'}--> | |
| <div class="privacy-item"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="advertisingReceiveMail" name="maillingFl" value="y" <!--{? data['maillingFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="single <!--{? data['maillingFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveMail">{=__('이메일 수신 동의')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| <!--{? advertisingReceiveSmsUse == 'y'}--> | |
| <div class="privacy-item"> | |
| <div class="privacy-head"> | |
| <span class="inp_chk"> | |
| <input type="checkbox" class="sp js_advertising_channel" id="advertisingReceiveSms" name="smsFl" value="y" <!--{? data['smsFl'] == 'y'}-->checked="checked"<!--{/}-->> | |
| <label class="single <!--{? data['smsFl'] == 'y'}-->on<!--{/}-->" for="advertisingReceiveSms">{=__('모바일 메시지 수신 동의')}</label> | |
| </span> | |
| </div> | |
| </div> | |
| <!--{/}--> | |
| </div> | |
| </div> | |
| </div> | |
| <!--{/ // isUseAdvertisingReceive end}--> | |
| <!--{/}--> | |
| <script type="text/javascript"> | |
| $(document).ready(function () { | |
| e.preventDefault(); | |
| $('p.msg').addClass('hidden'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.privacy-item'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| // 마수동/광수동 약관 전문 새창 열기 (전체보기) | |
| $('.js_agreement_view').on('click', function () { | |
| window.open('../service/agreement.php?code=' + $(this).data('code')); | |
| }); | |
| <!--{ ? useAppleLogin }--> | |
| $("#apple_btn").on("click", startClicked); | |
| function startClicked(){ | |
변경 전my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 후my_page.html
| e.preventDefault(); | |
| $('p.msg').addClass('dn'); | |
| var $target = $(e.target), $label = $target.siblings('label'), $termsView = $target.closest('.terms-view'); | |
| var isTermsAgreeSelect = (e.target.id === 'termsAgree3') || (e.target.id === 'termsAgree4') || (e.target.id === 'termsAgree5') || (e.target.id === 'termsAgree6') || (e.target.id === 'termsAgree7'); | |
| var isTargetChecked = $target.prop('checked') === true; | |
| if (isTargetChecked) { | |
| } | |
| }); | |
| /* | |
| * 광고성 수신 동의 ↔ 이메일/모바일 수신 동의 ↔ 마케팅 목적 개인정보 수집 및 이용 동의 연동 (마이페이지 전용) | |
| * - 광고성 수신 동의 체크 → 이메일/모바일 채널 일괄 + 마케팅 목적 동의 ON | |
| * - 채널(1개 이상) 체크 → 광고성 수신 동의 + 마케팅 목적 동의 ON (채널은 각각 개별 토글) | |
| * - 이 스크립트는 마이페이지(my_page.html)에서만 로드되므로 $(document) 위임으로 바인딩해도 회원가입 화면엔 적용되지 않음 | |
| * (광고성 체크박스가 #formJoin 밖에 렌더되는 경우가 있어 $formJoin 스코프는 사용하지 않음) | |
| */ | |
| const checkMarketingApproval = function () { | |
| $('#privateMarketingConsentOptionFl').prop('checked', true).val('y').siblings('label').addClass('on'); | |
| $('#termsAgree6').prop('checked', true).siblings('label').addClass('on'); | |
| }; | |
| $(document).on('change', '#termsAgree7', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $(this).siblings('label').toggleClass('on', isChecked); | |
| $('#advertisingReceiveAll').prop('checked', isChecked) | |
| .siblings('label').toggleClass('on', isChecked); | |
| $('.js_advertising_channel').prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $(document).on('change', '#advertisingReceiveAll', function () { | |
| const isChecked = $(this).prop('checked') === true; | |
| $('.js_advertising_channel').prop('checked', isChecked).val(isChecked ? 'y' : 'n') | |
| .siblings('label').toggleClass('on', isChecked); | |
| // 전체선택(advertisingReceiveAll) 직접 조작 시 광고성 수신 동의(termsAgree7) 헤더도 동기화 | |
| $('#termsAgree7').prop('checked', isChecked).siblings('label').toggleClass('on', isChecked); | |
| if (isChecked) { | |
| checkMarketingApproval(); | |
| } | |
| }); | |
| $(document).on('change', '.js_advertising_channel', function () { | |
| const anyChannelChecked = $('.js_advertising_channel:checked').length > 0; | |
| const allChannelChecked = $('.js_advertising_channel').length > 0 | |
| && $('.js_advertising_channel:not(:checked)').length === 0; | |
| $('#advertisingReceiveAll').prop('checked', anyChannelChecked) | |
| .siblings('label').toggleClass('on', anyChannelChecked); | |
| if (anyChannelChecked) { | |
| checkMarketingApproval(); | |
| } | |
| // 수신 채널 전부 선택 시 광고성 수신 동의(termsAgree7) 헤더 ON (일부만이면 켜지 않음) | |
| if (allChannelChecked) { | |
| $('#termsAgree7').prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| if ($(this).prop('checked') === false) { | |
| $('#termsAgree7').prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 체크 시 광고성 수신 동의·수신 채널 일괄 선택 | |
| const checkAdvertising = function () { | |
| if ($('#termsAgree7').length === 0) { | |
| return; | |
| } | |
| $('#termsAgree7').prop('checked', true).siblings('label').addClass('on'); | |
| $('#advertisingReceiveAll').prop('checked', true).siblings('label').addClass('on'); | |
| $('.js_advertising_channel').prop('checked', true).val('y').siblings('label').addClass('on'); | |
| }; | |
| $(document).on('change', '#privateMarketingConsentOptionFl', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } else { | |
| $('#termsAgree6').prop('checked', false).siblings('label').removeClass('on'); | |
| } | |
| }); | |
| // 마케팅 목적 개인정보 수집 및 이용 동의 그룹 [선택] 헤더 체크 시 광고성 수신 동의·수신 채널 연동 | |
| $(document).on('change', '#termsAgree6', function () { | |
| if ($(this).prop('checked') === true) { | |
| checkAdvertising(); | |
| } | |
| }); | |
| // 그룹 하위 항목이 모두 선택되면 상위 [선택] 헤더도 선택 (하나라도 해제 시 해제) | |
| $(document).on('change', '.privacy-head :checkbox', function () { | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6').each(function () { | |
| const $header = $(this); | |
| const $subs = $header.closest('.privacy-item').find(':checkbox').not($header); | |
| if ($subs.length === 0) { | |
| return; | |
| } | |
| const allChecked = $subs.not(':checked').length === 0; | |
| $header.prop('checked', allChecked).siblings('label').toggleClass('on', allChecked); | |
| }); | |
| }); | |
| // 초기 로드: 저장된 하위 선택 상태로 상위 [선택] 헤더 동기화 | |
| $('#termsAgree3, #termsAgree4, #termsAgree5, #termsAgree6').each(function () { | |
| const $subs = $(this).closest('.privacy-item').find(':checkbox').not(this); | |
| if ($subs.length > 0 && $subs.not(':checked').length === 0) { | |
| $(this).prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| }); | |
| // 초기 로드: 수신 채널이 전부 선택된 상태면 광고성 수신 동의(termsAgree7) 헤더 ON | |
| if ($('.js_advertising_channel').length > 0 | |
| && $('.js_advertising_channel:not(:checked)').length === 0) { | |
| $('#termsAgree7').prop('checked', true).siblings('label').addClass('on'); | |
| } | |
| select_email_domain('email'); | |
| <!--{? (joinField.marriFl.use == 'y' && joinField.marriDate.use == 'y') || joinField.birthDt.use == 'y' }--> | |
변경 전delivery_regist.php
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| <tbody> | |
| <tr> | |
| </script> | |
| <script type="text/html" id="templateMethodEtc"> | |
| <tr> | |
| <th>배송비 설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </script> | |
| <script type="text/html" id="templateMethodEtcRangeRepeat"> | |
| <tr> | |
| <th>배송비 설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </td> | |
| </tr> | |
| </script> | |
| <script type="text/javascript"> | |
| <!-- | |
| var data = <?=json_encode($data)?>; | |
| * @param string fixMethod 배송비 책정 방법 | |
| */ | |
| var defaultMethod, defaultDeliveryConfigType, defaultRangeRepeat; | |
| function form_delivery_charge(fixMethod) { | |
| deliveryConfigType(); | |
| // 배송비설정 초기화 | |
| form_delivery_charge(fixFl); | |
| // 금액 입력부 초기화 | |
| $('input[name*=\'[unitStart]\']').number_only(); | |
| $('input[name*=\'[unitEnd]\']').number_only(); | |
| $('#basic_fixFl').change(function () { | |
| fixFl = this.value; | |
| form_delivery_charge(this.value); | |
| }); | |
| // 공급사 구분 선택 이벤트 | |
| else { | |
| $('#areaGroupSelect').hide(); | |
| } | |
| }); | |
| // 출고지/반품/교환지 주소 토글 | |
변경 후delivery_regist.php
| </div> | |
| </td> | |
| </tr> | |
| <tr id="areaChargeRepeatArea"<?= (in_array($data['basic']['fixFl'], ['count', 'weight']) && $data['basic']['areaFl'] == 'y') ? '' : ' style="display:none;"' ?>> | |
| <th>지역별 추가배송비<br>부과방법 | |
| <button type="button" class="btn btn-xs js-area-charge-repeat-help"><span class="icon-tooltip"></span></button> | |
| </th> | |
| <td colspan="3"> | |
| <label class="radio-inline"> | |
| <input type="radio" name="basic[areaChargeRepeatFl]" value="n" <?= $checked['areaChargeRepeatFl']['n'] ?? '' ?> /> 배송비 구간에 상관없이 1회 부과 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="basic[areaChargeRepeatFl]" value="y" <?= $checked['areaChargeRepeatFl']['y'] ?? '' ?> /> 배송비 구간마다 반복 부과 | |
| </label> | |
| </td> | |
| </tr> | |
| </tbody> | |
| <tbody> | |
| <tr> | |
| </script> | |
| <script type="text/html" id="templateMethodEtc"> | |
| <tr> | |
| <th>배송비 <%= (fixMethod == 'count' || fixMethod == 'weight') ? '구간 ' : '' %>설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </script> | |
| <script type="text/html" id="templateMethodEtcRangeRepeat"> | |
| <tr> | |
| <th>배송비 <%= (fixMethod == 'count' || fixMethod == 'weight') ? '구간 ' : '' %>설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </td> | |
| </tr> | |
| </script> | |
| <!-- 지역별 추가배송비 부과방법 도움말 (팝오버 콘텐츠) --> | |
| <div id="areaChargeRepeatHelp" class="display-none"> | |
| <p><strong>배송비 구간에 상관없이 1회 부과</strong><br/> | |
| - 주문한 상품의 수량, 무게에 상관없이 지역별 추가 배송비가 1회만 부과됩니다.</p> | |
| <p><strong>배송비 구간마다 반복 부과</strong><br/> | |
| - 배송비 구간 설정에서 입력한 수량, 무게 범위 구간마다 지역별 추가 배송비가 추가 부과됩니다.</p> | |
| <table class="table table-cols"> | |
| <colgroup><col style="width:60%"/><col style="width:40%"/></colgroup> | |
| <thead><tr><th>구매수량 범위</th><th>배송비</th></tr></thead> | |
| <tbody> | |
| <tr><td>0개 이상 ~ 2개 미만일 때</td><td>1,000원</td></tr> | |
| <tr><td>3개 이상</td><td>3,000원</td></tr> | |
| </tbody> | |
| </table> | |
| <p>: 지역별 배송비가 500원일 때, 4개 구매 시 지역별 배송비가 2회 부과되어<br/> | |
| 총 배송비는 3,000원 + (500원 x 2) = 4,000원</p> | |
| <p>- 범위 반복이 설정된 경우 입력한 수량, 무게 단위로 지역별 배송비가 추가 부과됩니다.</p> | |
| <table class="table table-cols"> | |
| <colgroup><col style="width:60%"/><col style="width:40%"/></colgroup> | |
| <thead><tr><th>구매수량 범위</th><th>배송비</th></tr></thead> | |
| <tbody> | |
| <tr><td>0개 이상 ~ 2개 미만일 때</td><td>1,000원</td></tr> | |
| <tr><td>2개 이상 ~ 2개 마다 반복 부과</td><td>2,000원</td></tr> | |
| </tbody> | |
| </table> | |
| <p>: 지역별 배송비가 500원일 때, 6개 구매 시 지역별 배송비가 4회 부과되어<br/> | |
| 총 배송비는 1,000원 + (2,000원 x 3) + (500원 x 4) = 9,000원</p> | |
| </div> | |
| <style> | |
| button.js-area-charge-repeat-help { background-color: transparent; margin: 0; } | |
| .area-charge-repeat-popover { max-width: 480px; } | |
| .area-charge-repeat-popover .popover-content { padding: 15px; } | |
| .area-charge-repeat-popover table { margin-bottom: 8px; } | |
| .area-charge-repeat-popover table td { text-align: left; } | |
| .area-charge-repeat-popover .popover-content { text-align: left; } | |
| </style> | |
| <script type="text/javascript"> | |
| <!-- | |
| var data = <?=json_encode($data)?>; | |
| * @param string fixMethod 배송비 책정 방법 | |
| */ | |
| var defaultMethod, defaultDeliveryConfigType, defaultRangeRepeat; | |
| /** | |
| * 지역별 추가배송비 부과방법(1회/구간반복) 노출 토글 | |
| * 노출조건: 배송비 유형이 수량별/무게별 이고, 지역별 추가배송비가 "있음"일 때만 | |
| */ | |
| function toggleAreaChargeRepeat() { | |
| var fixFlVal = $('#basic_fixFl').val(); | |
| var areaFlVal = $('input[name="basic[areaFl]"]:checked').val(); | |
| if ((fixFlVal == 'count' || fixFlVal == 'weight') && areaFlVal == 'y') { | |
| $('#areaChargeRepeatArea').show(); | |
| } else { | |
| $('#areaChargeRepeatArea').hide(); | |
| } | |
| } | |
| function form_delivery_charge(fixMethod) { | |
| deliveryConfigType(); | |
| // 배송비설정 초기화 | |
| form_delivery_charge(fixFl); | |
| // 지역별 추가배송비 부과방법 노출 초기화 | |
| toggleAreaChargeRepeat(); | |
| // 지역별 추가배송비 부과방법 도움말 팝오버 | |
| $('.js-area-charge-repeat-help').popover({ | |
| trigger: 'hover', | |
| container: '#content', | |
| html: true, | |
| sanitize: false, | |
| placement: 'right', | |
| content: function () { | |
| return $('#areaChargeRepeatHelp').html(); | |
| }, | |
| template: '<div class="popover area-charge-repeat-popover" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>' | |
| }); | |
| // 금액 입력부 초기화 | |
| $('input[name*=\'[unitStart]\']').number_only(); | |
| $('input[name*=\'[unitEnd]\']').number_only(); | |
| $('#basic_fixFl').change(function () { | |
| fixFl = this.value; | |
| form_delivery_charge(this.value); | |
| toggleAreaChargeRepeat(); | |
| }); | |
| // 공급사 구분 선택 이벤트 | |
| else { | |
| $('#areaGroupSelect').hide(); | |
| } | |
| toggleAreaChargeRepeat(); | |
| }); | |
| // 출고지/반품/교환지 주소 토글 | |
변경 전delivery_regist.php
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| <tbody> | |
| <tr> | |
| </script> | |
| <script type="text/html" id="templateMethodEtc"> | |
| <tr> | |
| <th>배송비 설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </script> | |
| <script type="text/html" id="templateMethodEtcRangeRepeat"> | |
| <tr> | |
| <th>배송비 설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </tr> | |
| </script> | |
| <script type="text/javascript"> | |
| <!-- | |
| var data = <?=json_encode($data)?>; | |
| * @param string fixMethod 배송비 책정 방법 | |
| */ | |
| var defaultMethod, defaultDeliveryConfigType, defaultRangeRepeat; | |
| function form_delivery_charge(fixMethod) { | |
| deliveryConfigType(); | |
| // 배송비설정 초기화 | |
| form_delivery_charge(fixFl); | |
| // 금액 입력 초기화 | |
| $('input[name*=\'[unitStart]\']').number_only(); | |
| $('input[name*=\'[unitEnd]\']').number_only(); | |
| console.log($('#basic_fixFl option:selected').val()); | |
| fixFl = this.value; | |
| form_delivery_charge(this.value); | |
| }); | |
| // 삭제 버튼 클릭시 이벤트 | |
| else { | |
| $('#areaGroupSelect').hide(); | |
| } | |
| }); | |
| // 출고지/반품/교환지 주소 토글 | |
변경 후delivery_regist.php
| </div> | |
| </td> | |
| </tr> | |
| <tr id="areaChargeRepeatArea"<?= (in_array($data['basic']['fixFl'], ['count', 'weight']) && $data['basic']['areaFl'] == 'y') ? '' : ' style="display:none;"' ?>> | |
| <th>지역별 추가배송비<br>부과방법 | |
| <button type="button" class="btn btn-xs js-area-charge-repeat-help"><span class="icon-tooltip"></span></button> | |
| </th> | |
| <td colspan="3"> | |
| <label class="radio-inline"> | |
| <input type="radio" name="basic[areaChargeRepeatFl]" value="n" <?= $checked['areaChargeRepeatFl']['n'] ?? '' ?> /> 배송비 구간에 상관없이 1회 부과 | |
| </label> | |
| <label class="radio-inline"> | |
| <input type="radio" name="basic[areaChargeRepeatFl]" value="y" <?= $checked['areaChargeRepeatFl']['y'] ?? '' ?> /> 배송비 구간마다 반복 부과 | |
| </label> | |
| </td> | |
| </tr> | |
| </tbody> | |
| <tbody> | |
| <tr> | |
| </script> | |
| <script type="text/html" id="templateMethodEtc"> | |
| <tr> | |
| <th>배송비 <%= (fixMethod == 'count' || fixMethod == 'weight') ? '구간 ' : '' %>설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </script> | |
| <script type="text/html" id="templateMethodEtcRangeRepeat"> | |
| <tr> | |
| <th>배송비 <%= (fixMethod == 'count' || fixMethod == 'weight') ? '구간 ' : '' %>설정(<%=strTitle%>별)</th> | |
| <td colspan="3"> | |
| <% if (deliveryConfigType == 'all') { %> | |
| <table id="basicDeliveryConfigFeeForm" class="table table-cols mgb0"> | |
| </tr> | |
| </script> | |
| <!-- 지역별 추가배송비 부과방법 도움말 (팝오버 콘텐츠) --> | |
| <div id="areaChargeRepeatHelp" class="display-none"> | |
| <p><strong>배송비 구간에 상관없이 1회 부과</strong><br/> | |
| - 주문한 상품의 수량, 무게에 상관없이 지역별 추가 배송비가 1회만 부과됩니다.</p> | |
| <p><strong>배송비 구간마다 반복 부과</strong><br/> | |
| - 배송비 구간 설정에서 입력한 수량, 무게 범위 구간마다 지역별 추가 배송비가 추가 부과됩니다.</p> | |
| <table class="table table-cols"> | |
| <colgroup><col style="width:60%"/><col style="width:40%"/></colgroup> | |
| <thead><tr><th>구매수량 범위</th><th>배송비</th></tr></thead> | |
| <tbody> | |
| <tr><td>0개 이상 ~ 2개 미만일 때</td><td>1,000원</td></tr> | |
| <tr><td>3개 이상</td><td>3,000원</td></tr> | |
| </tbody> | |
| </table> | |
| <p>: 지역별 배송비가 500원일 때, 4개 구매 시 지역별 배송비가 2회 부과되어<br/> | |
| 총 배송비는 3,000원 + (500원 x 2) = 4,000원</p> | |
| <p>- 범위 반복이 설정된 경우 입력한 수량, 무게 단위로 지역별 배송비가 추가 부과됩니다.</p> | |
| <table class="table table-cols"> | |
| <colgroup><col style="width:60%"/><col style="width:40%"/></colgroup> | |
| <thead><tr><th>구매수량 범위</th><th>배송비</th></tr></thead> | |
| <tbody> | |
| <tr><td>0개 이상 ~ 2개 미만일 때</td><td>1,000원</td></tr> | |
| <tr><td>2개 이상 ~ 2개 마다 반복 부과</td><td>2,000원</td></tr> | |
| </tbody> | |
| </table> | |
| <p>: 지역별 배송비가 500원일 때, 6개 구매 시 지역별 배송비가 4회 부과되어<br/> | |
| 총 배송비는 1,000원 + (2,000원 x 3) + (500원 x 4) = 9,000원</p> | |
| </div> | |
| <style> | |
| button.js-area-charge-repeat-help { background-color: transparent; margin: 0; } | |
| .area-charge-repeat-popover { max-width: 480px; } | |
| .area-charge-repeat-popover .popover-content { padding: 15px; } | |
| .area-charge-repeat-popover table { margin-bottom: 8px; } | |
| .area-charge-repeat-popover table td { text-align: left; } | |
| .area-charge-repeat-popover .popover-content { text-align: left; } | |
| </style> | |
| <script type="text/javascript"> | |
| <!-- | |
| var data = <?=json_encode($data)?>; | |
| * @param string fixMethod 배송비 책정 방법 | |
| */ | |
| var defaultMethod, defaultDeliveryConfigType, defaultRangeRepeat; | |
| /** | |
| * 지역별 추가배송비 부과방법(1회/구간반복) 노출 토글 | |
| * 노출조건: 배송비 유형이 수량별/무게별 이고, 지역별 추가배송비가 "있음"일 때만 | |
| */ | |
| function toggleAreaChargeRepeat() { | |
| var fixFlVal = $('#basic_fixFl').val(); | |
| var areaFlVal = $('input[name="basic[areaFl]"]:checked').val(); | |
| if ((fixFlVal == 'count' || fixFlVal == 'weight') && areaFlVal == 'y') { | |
| $('#areaChargeRepeatArea').show(); | |
| } else { | |
| $('#areaChargeRepeatArea').hide(); | |
| } | |
| } | |
| function form_delivery_charge(fixMethod) { | |
| deliveryConfigType(); | |
| // 배송비설정 초기화 | |
| form_delivery_charge(fixFl); | |
| // 지역별 추가배송비 부과방법 노출 초기화 | |
| toggleAreaChargeRepeat(); | |
| // 지역별 추가배송비 부과방법 도움말 팝오버 | |
| $('.js-area-charge-repeat-help').popover({ | |
| trigger: 'hover', | |
| container: '#content', | |
| html: true, | |
| sanitize: false, | |
| placement: 'right', | |
| content: function () { | |
| return $('#areaChargeRepeatHelp').html(); | |
| }, | |
| template: '<div class="popover area-charge-repeat-popover" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>' | |
| }); | |
| // 금액 입력 초기화 | |
| $('input[name*=\'[unitStart]\']').number_only(); | |
| $('input[name*=\'[unitEnd]\']').number_only(); | |
| console.log($('#basic_fixFl option:selected').val()); | |
| fixFl = this.value; | |
| form_delivery_charge(this.value); | |
| toggleAreaChargeRepeat(); | |
| }); | |
| // 삭제 버튼 클릭시 이벤트 | |
| else { | |
| $('#areaGroupSelect').hide(); | |
| } | |
| toggleAreaChargeRepeat(); | |
| }); | |
| // 출고지/반품/교환지 주소 토글 | |
변경 전Cart.php
| if ($sameGoodsDeliveryFl !== 'y') { | |
| // 배송비 계산 | |
| if ($tmp['deliveryByCalculate'] === 'y') { | |
| if ($getDeliveryInfo[$deliverySno]['rangeRepeat'] === 'y') { | |
| //범위 반복 설정이 되어있는 경우 | |
| $deliveryStandardFinal = 0; | |
| } | |
| $goodsDeliveryPrice += ($deliveryStandardFinal * $conditionRepeat['price']); | |
| } | |
| } | |
| } | |
| } | |
| if ($tmp['deliveryByStandard'] >= $cVal['unitStart'] && $tmp['deliveryByStandard'] < $cVal['unitEnd']) { | |
| $goodsDeliveryPrice = $cVal['price']; | |
| continue; | |
| } | |
| } | |
| } | |
| } | |
| // 방문수령 배송비 무료 처리 | |
| if (isset($setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl']) === false || empty($setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl']) === true) { | |
| $setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl'] = $goodsDeliveryCollectFl; | |
| } | |
| } | |
| } | |
| // 배송비조건별 계산 | |
| // SCM 번호 설정 | |
| $scmNo = $deliveryCond['scmNo']; | |
| // 배송비 계산 | |
| if ($deliveryCond['deliveryByCalculate'] === 'y') { | |
| foreach ($setDeliveryCharge as $cKey => $cVal) { | |
| $deliveryStandardFinal += 1; | |
| } | |
| $rangeRepeatPrice += ($deliveryStandardFinal * $cVal['price']); | |
| } | |
| } | |
| } | |
| //범위반복 미사용일 시 | |
| if ($deliveryCond['deliveryByStandard'] >= $cVal['unitStart'] && $deliveryCond['deliveryByStandard'] < $cVal['unitEnd']) { | |
| $conditionSatisfy = true; | |
| } | |
| } | |
| $checkZeroPrice = true; | |
| StringUtils::strIsSet($deliveryCond['goodsDeliveryAreaPrice'], 0); | |
| if ($deliveryCond['goodsDeliveryAreaPrice'] > 0) { | |
| $deliveryCond['goodsDeliveryCollectPrice'] += $deliveryCond['goodsDeliveryAreaPrice']; | |
| } | |
| } | |
| } | |
| } | |
| // 상품별 지역배송비 총 배송 금액 | |
| gd_isset($this->totalGoodsDeliveryAreaPrice[$key], 0); | |
| if ($multiShippingFl == 'y') gd_isset($this->totalGoodsMultiDeliveryAreaPrice[$orderInfoCd][$key], 0); | |
변경 후Cart.php
| if ($sameGoodsDeliveryFl !== 'y') { | |
| // 배송비 계산 | |
| if ($tmp['deliveryByCalculate'] === 'y') { | |
| $areaChargeRepeatCount = 1; // 지역별 추가배송비 반복 구간 순번 (기본 1회) | |
| if ($getDeliveryInfo[$deliverySno]['rangeRepeat'] === 'y') { | |
| //범위 반복 설정이 되어있는 경우 | |
| $deliveryStandardFinal = 0; | |
| } | |
| $goodsDeliveryPrice += ($deliveryStandardFinal * $conditionRepeat['price']); | |
| $areaChargeRepeatCount = $deliveryStandardFinal + 1; // 범위반복: 첫 구간(1) + 반복 횟수 | |
| } | |
| } | |
| } | |
| } | |
| if ($tmp['deliveryByStandard'] >= $cVal['unitStart'] && $tmp['deliveryByStandard'] < $cVal['unitEnd']) { | |
| $goodsDeliveryPrice = $cVal['price']; | |
| $areaChargeRepeatCount = $cKey + 1; // 매칭 구간 순번 | |
| continue; | |
| } | |
| } | |
| } | |
| // 지역별 추가배송비 구간 반복 부과 | |
| // 부과방법이 '구간마다 반복(Y)'이면 매칭 구간 순번(N)만큼 지역배송비를 곱한다 | |
| if ($getDeliveryInfo[$deliverySno]['areaChargeRepeatFl'] === 'y' && $goodsDeliveryAreaPrice > 0) { | |
| $goodsDeliveryAreaPrice = $goodsDeliveryAreaPrice * $areaChargeRepeatCount; | |
| } | |
| } | |
| // 방문수령 배송비 무료 처리 | |
| if (isset($setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl']) === false || empty($setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl']) === true) { | |
| $setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryCollectFl'] = $goodsDeliveryCollectFl; | |
| } | |
| // 지역별 추가배송비 '구간마다 반복(y)'인 경우, 매칭 구간 순번(N) 곱셈을 위해 getDeliveryCond 로 전달 | |
| if ($getDeliveryInfo[$deliverySno]['areaChargeRepeatFl'] === 'y' && $goodsDeliveryAreaPrice > 0) { | |
| $setDeliveryCond[$deliverySno][$gVal['goodsNo']]['goodsDeliveryAreaPrice'] = $goodsDeliveryAreaPrice; | |
| $goodsDeliveryAreaPrice = 0; | |
| } | |
| } | |
| } | |
| // 배송비조건별 계산 | |
| // SCM 번호 설정 | |
| $scmNo = $deliveryCond['scmNo']; | |
| $areaChargeRepeatCount = 1; // 지역별 추가배송비 반복 구간 순번 (기본 1회) | |
| // 배송비 계산 | |
| if ($deliveryCond['deliveryByCalculate'] === 'y') { | |
| foreach ($setDeliveryCharge as $cKey => $cVal) { | |
| $deliveryStandardFinal += 1; | |
| } | |
| $rangeRepeatPrice += ($deliveryStandardFinal * $cVal['price']); | |
| $areaChargeRepeatCount = $deliveryStandardFinal + 1; // 범위반복: 첫 구간(1) + 반복 횟수 | |
| } | |
| } | |
| } | |
| //범위반복 미사용일 시 | |
| if ($deliveryCond['deliveryByStandard'] >= $cVal['unitStart'] && $deliveryCond['deliveryByStandard'] < $cVal['unitEnd']) { | |
| $conditionSatisfy = true; | |
| $areaChargeRepeatCount = $cKey + 1; // 매칭 구간 순번 | |
| } | |
| } | |
| $checkZeroPrice = true; | |
| StringUtils::strIsSet($deliveryCond['goodsDeliveryAreaPrice'], 0); | |
| if ($deliveryCond['goodsDeliveryAreaPrice'] > 0) { | |
| // 지역별 추가배송비 구간 반복 부과 (착불도 매칭 구간 순번 N만큼 합산) | |
| $repeatedAreaPrice = $deliveryCond['goodsDeliveryAreaPrice']; | |
| if ($deliveryInfo['areaChargeRepeatFl'] === 'y') { | |
| $repeatedAreaPrice = $repeatedAreaPrice * $areaChargeRepeatCount; | |
| } | |
| $deliveryCond['goodsDeliveryCollectPrice'] += $repeatedAreaPrice; | |
| } | |
| } | |
| } | |
| } | |
| // 지역별 추가배송비 구간 반복 부과 | |
| // 부과방법이 '구간마다 반복(Y)'이면 매칭 구간 순번(N)만큼 지역배송비를 곱한다 | |
| if ($deliveryInfo['areaChargeRepeatFl'] === 'y' && $deliveryCond['deliveryByCalculate'] === 'y' && !empty($deliveryCond['goodsDeliveryAreaPrice'])) { | |
| $deliveryCond['goodsDeliveryAreaPrice'] = $deliveryCond['goodsDeliveryAreaPrice'] * $areaChargeRepeatCount; | |
| } | |
| // 상품별 지역배송비 총 배송 금액 | |
| gd_isset($this->totalGoodsDeliveryAreaPrice[$key], 0); | |
| if ($multiShippingFl == 'y') gd_isset($this->totalGoodsMultiDeliveryAreaPrice[$orderInfoCd][$key], 0); | |
변경 전DBTableField.php
| ['val' => 'dmVisitAddressUseFl', 'typ' => 's', 'def' => 'n'], // 방문수령지 상품상세노출여부 | |
| ['val' => 'rangeRepeat', 'typ' => 's', 'def' => 'n'], // 범위반복구간여부 | |
| ['val' => 'addGoodsCountInclude', 'typ' => 's', 'def' => 'n'], // 수량별배송비 추가옵션수량 포함여부 | |
| ]; | |
| // @formatter:on | |
변경 후DBTableField.php
| ['val' => 'dmVisitAddressUseFl', 'typ' => 's', 'def' => 'n'], // 방문수령지 상품상세노출여부 | |
| ['val' => 'rangeRepeat', 'typ' => 's', 'def' => 'n'], // 범위반복구간여부 | |
| ['val' => 'addGoodsCountInclude', 'typ' => 's', 'def' => 'n'], // 수량별배송비 추가옵션수량 포함여부 | |
| ['val' => 'areaChargeRepeatFl', 'typ' => 's', 'def' => 'n'], // 지역별 추가배송비 부과방법 (y:구간마다 반복 / n:1회) | |
| ]; | |
| // @formatter:on | |
변경 전DeliveryCart.php
| 'rangeLimitWeight', | |
| 'rangeRepeat', | |
| 'addGoodsCountInclude', | |
| 'deliveryMethodFl', | |
| 'deliveryVisitPayFl', | |
| 'deliveryConfigType', | |
변경 후DeliveryCart.php
| 'rangeLimitWeight', | |
| 'rangeRepeat', | |
| 'addGoodsCountInclude', | |
| 'areaChargeRepeatFl', | |
| 'deliveryMethodFl', | |
| 'deliveryVisitPayFl', | |
| 'deliveryConfigType', | |
변경 전Delivery.php
| $data['basic']['dmVisitTypeDisplayFl'] = gd_isset($arrData['basic']['dmVisitTypeDisplayFl'], 'n'); | |
| $data['basic']['rangeRepeat'] = gd_isset($arrData['basic']['rangeRepeat'], 'n'); | |
| $data['basic']['addGoodsCountInclude'] = gd_isset($arrData['basic']['addGoodsCountInclude'], 'n'); | |
| $data['basic']['deliveryVisitPayFl'] = gd_isset($arrData['basic']['deliveryVisitPayFl'], 'y'); | |
| $data['basic']['dmVisitAddressUseFl'] = gd_isset($arrData['basic']['dmVisitAddressUseFl'], 'n'); | |
| $data['basic']['sameGoodsDeliveryFl'] = gd_isset($arrData['basic']['sameGoodsDeliveryFl'], 'n'); | |
변경 후Delivery.php
| $data['basic']['dmVisitTypeDisplayFl'] = gd_isset($arrData['basic']['dmVisitTypeDisplayFl'], 'n'); | |
| $data['basic']['rangeRepeat'] = gd_isset($arrData['basic']['rangeRepeat'], 'n'); | |
| $data['basic']['addGoodsCountInclude'] = gd_isset($arrData['basic']['addGoodsCountInclude'], 'n'); | |
| $data['basic']['areaChargeRepeatFl'] = $arrData['basic']['areaChargeRepeatFl'] ?? 'n'; | |
| $data['basic']['deliveryVisitPayFl'] = gd_isset($arrData['basic']['deliveryVisitPayFl'], 'y'); | |
| $data['basic']['dmVisitAddressUseFl'] = gd_isset($arrData['basic']['dmVisitAddressUseFl'], 'n'); | |
| $data['basic']['sameGoodsDeliveryFl'] = gd_isset($arrData['basic']['sameGoodsDeliveryFl'], 'n'); | |
변경 전DeliveryRegistController.php
| gd_isset($data['basic']['dmVisitTypeFl'], 'same'); | |
| gd_isset($data['basic']['dmVisitTypeDisplayFl'], 'n'); | |
| gd_isset($data['basic']['rangeRepeat'], 'n'); | |
| gd_isset($data['manage']['scmNo'], (Manager::isProvider() && !Request::get()->has('sno') ? Session::get('manager.scmNo') : $data['manage']['scmNo'])); | |
| gd_isset($data['basic']['deliveryConfigType'], 'all'); | |
| $checked['dmVisitAddressUseFl'][$data['basic']['dmVisitAddressUseFl']] = | |
| $checked['rangeRepeat'][$data['basic']['rangeRepeat']] = | |
| $checked['addGoodsCountInclude'][$data['basic']['addGoodsCountInclude']] = | |
| $checked['deliveryConfigType'][$data['basic']['deliveryConfigType']] = 'checked="checked"'; | |
| //배송 방식 | |
변경 후DeliveryRegistController.php
| gd_isset($data['basic']['dmVisitTypeFl'], 'same'); | |
| gd_isset($data['basic']['dmVisitTypeDisplayFl'], 'n'); | |
| gd_isset($data['basic']['rangeRepeat'], 'n'); | |
| $data['basic']['areaChargeRepeatFl'] = $data['basic']['areaChargeRepeatFl'] ?? 'n'; | |
| gd_isset($data['manage']['scmNo'], (Manager::isProvider() && !Request::get()->has('sno') ? Session::get('manager.scmNo') : $data['manage']['scmNo'])); | |
| gd_isset($data['basic']['deliveryConfigType'], 'all'); | |
| $checked['dmVisitAddressUseFl'][$data['basic']['dmVisitAddressUseFl']] = | |
| $checked['rangeRepeat'][$data['basic']['rangeRepeat']] = | |
| $checked['addGoodsCountInclude'][$data['basic']['addGoodsCountInclude']] = | |
| $checked['areaChargeRepeatFl'][$data['basic']['areaChargeRepeatFl']] = | |
| $checked['deliveryConfigType'][$data['basic']['deliveryConfigType']] = 'checked="checked"'; | |
| //배송 방식 | |
변경 전layer.css
| #wrap .ly_wrap.delivery_layer{width:305px; top:0px; left:-219px;} | |
| /* 지역별추가배송비 레이어 */ | |
| #wrap .ly_wrap.delivery_zone_layer{width:305px; top:0px; left:-94px;} | |
| .delivery_zone_layer .delivery_list{overflow-y:scroll; max-height:200px;} | |
| /* 배송비 레잉어 공통 영역 */ | |
| .ly_wrap .delivery_list ul{border-bottom:1px solid #e8e8e8;} | |
| .ly_wrap .delivery_list ul li{padding:10px 5px 10px 5px; font-weight:bold; border-top:1px solid #e8e8e8;} | |
변경 후layer.css
| #wrap .ly_wrap.delivery_layer{width:305px; top:0px; left:-219px;} | |
| /* 지역별추가배송비 레이어 */ | |
| #wrap .ly_wrap.delivery_zone_layer{width:305px; top:0px; left:-94px;} | |
| .delivery_zone_layer .delivery_list{overflow-y:auto; max-height:200px;} | |
| /* 배송비 레잉어 공통 영역 */ | |
| .ly_wrap .delivery_list ul{border-bottom:1px solid #e8e8e8;} | |
| .ly_wrap .delivery_list ul li{padding:10px 5px 10px 5px; font-weight:bold; border-top:1px solid #e8e8e8;} | |
변경 전goods_view.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="chk_none">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="chk_none">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 전layer_option.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 후layer_option.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="chk_none">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="chk_none">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 전layer.css
| } | |
| .delivery_zone_layer .delivery_list { | |
| overflow-y: scroll; | |
| max-height: 200px; | |
| } | |
| /* 배송비 레잉어 공통 영역 */ | |
| .ly_wrap .delivery_list ul { | |
| border-bottom: 1px solid #e8e8e8; | |
변경 후layer.css
| } | |
| .delivery_zone_layer .delivery_list { | |
| overflow-y: auto; | |
| max-height: 200px; | |
| } | |
| .delivery_zone_layer .chk_none { | |
| padding: 5px 0 5px 19px; | |
| background-image: url('../../../img/icon/etc/icon_warning_green.svg'); | |
| } | |
| /* 배송비 레잉어 공통 영역 */ | |
| .ly_wrap .delivery_list ul { | |
| border-bottom: 1px solid #e8e8e8; | |
변경 전goods_view.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="chk_none">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="chk_none">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 전layer_option.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 후layer_option.html
| <!--{ / }--> | |
| </ul> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="chk_none">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="chk_none">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| <!-- //ly_cont --> | |
| <a href="#close" class="ly_close"><img src="../img/common/layer/btn_layer_close.png" alt="{=__('닫기')}"></a> | |
변경 전icon_warning_green.svg
변경 후icon_warning_green.svg
| <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <rect x="0.5" y="0.5" width="13" height="13" rx="6.5" stroke="#0cc472"/> | |
| <path d="M4.4541 7.51363V6.36328H9.54501V7.51363H4.4541Z" fill="white"/> | |
| <path d="M7.91618 3L7.76051 8.53342H6.22775L6.07208 3H7.91618ZM6.00023 10.0832C5.98826 9.58117 6.44329 9.1719 7.0061 9.17735C7.53898 9.1719 8 9.58117 8 10.0832C8 10.5907 7.53898 11 7.0061 11C6.44329 11 5.98826 10.5907 6.00023 10.0832Z" fill="#0cc472"/> | |
| </svg> | |
변경 전gd_share.css
| border: 1px solid #555; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer .wrap > strong, | |
| .option-layer .view .content-section .list .delivery-layer .wrap > strong { | |
| display: block; | |
변경 후gd_share.css
| border: 1px solid #555; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer.delivery-area, | |
| .option-layer .view .content-section .list .delivery-layer.delivery-area { | |
| height: auto; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer.delivery-area .wrap, | |
| .option-layer .view .content-section .list .delivery-layer.delivery-area .wrap { | |
| height: auto; | |
| padding-bottom: 9px; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer.delivery-area .wrap div, | |
| .option-layer .view .content-section .list .delivery-layer.delivery-area .wrap div { | |
| height: auto; | |
| max-height: 219px; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer.delivery-area .wrap .caution-msg1, | |
| .option-layer .view .content-section .list .delivery-layer.delivery-area .wrap .caution-msg1 { | |
| margin: 12px 9px 3px 19px; | |
| } | |
| .goods-view .goods .info .item ul li.delivery .delivery-layer .wrap > strong, | |
| .option-layer .view .content-section .list .delivery-layer .wrap > strong { | |
| display: block; | |
변경 전goods_view.html
| <!--{ / }--> | |
| </table> | |
| </div> | |
| <button type="button" class="close target-delivery-area" title="{=__('닫기')}">{=__('닫기')}</button> | |
| </div> | |
| </div> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </table> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="caution-msg1">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="caution-msg1">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| <button type="button" class="close target-delivery-area" title="{=__('닫기')}">{=__('닫기')}</button> | |
| </div> | |
| </div> | |
변경 전layer_option.html
| <!--{ / }--> | |
| </table> | |
| </div> | |
| <button type="button" class="target-delivery-area" title="{=__('닫기')}">{=__('닫기')}</button> | |
| </div> | |
| </div> | |
변경 후layer_option.html
| <!--{ / }--> | |
| </table> | |
| </div> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p class="caution-msg1">{=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p class="caution-msg1">{=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| <button type="button" class="target-delivery-area" title="{=__('닫기')}">{=__('닫기')}</button> | |
| </div> | |
| </div> | |
변경 전goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| </div> | |
변경 전goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| </div> | |
변경 전goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
변경 후goods_view.html
| <!--{ / }--> | |
| </tbody> | |
| </table> | |
| <!--{ ? goodsView['delivery']['basic']['areaChargeRepeatFl'] == 'y' }--> | |
| <!--{ ? goodsView['delivery']['basic']['fixFl'] == 'count' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 수량이 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ : goodsView['delivery']['basic']['fixFl'] == 'weight' }--> | |
| <p style="margin:8px 0 0;padding:5px 10px;color:#ab3e55;font-size:12px;line-height:1.4;">※ {=__('주문 무게가 속한 배송비 구간 수만큼, 지역별추가배송비가 반복 부과됩니다.')}</p> | |
| <!--{ / }--> | |
| <!--{ / }--> | |
| </div> | |
| </div> | |
| </div> | |
변경 전layout_design_editor.php
| skinCountry: '<?=$skinCountry?>', | |
| skinLiveFl: <?=$skinLiveFl ? 'true' : 'false'?>, | |
| rootSkinCode: '<?=$rootSkinCode?>', | |
| requestUrl: baseDir + '/design_editor_ps.php' | |
| }); | |
| }); | |
| </script> | |
변경 후layout_design_editor.php
| skinCountry: '<?=$skinCountry?>', | |
| skinLiveFl: <?=$skinLiveFl ? 'true' : 'false'?>, | |
| rootSkinCode: '<?=$rootSkinCode?>', | |
| requestUrl: baseDir + '/design_editor_ps.php', | |
| shopNo: <?=$clickLogShopNo ?? 0?>, | |
| adminIdHash: '<?=$clickLogAdminIdHash ?? ''?>' | |
| }); | |
| }); | |
| </script> | |
변경 전Board.php
| const TEXT_INSUFFICIENT_INPUTDATA = '입력 정보가 부족합니다'; | |
| const TEXT_NOTMATCH_PASSWORD = '비밀번호가 일치하지 않습니다'; | |
| const TEXT_NOTHAVE_AUTHORITY = '%s권한이 없습니다.'; | |
| const TEXT_UPLOAD_IMPOSSIBLE = '업로드가 불가능합니다'; | |
| const EXCEPTION_CODE_AUTH = 700; | |
| const UPLOAD_DEFAULT_MAX_SIZE = 5; //업로드 최대용량 디플트 값(mb) | |
| if($result['cnt']>0) { | |
| throw new \Exception(__("중복된 게시물을 연속으로 등록할 수 없습니다. \n중복 게시물이 아닌 경우, 잠시 후 다시 등록하시기 바랍니다.")); | |
| } | |
| } | |
| return true; | |
| } | |
변경 후Board.php
| const TEXT_INSUFFICIENT_INPUTDATA = '입력 정보가 부족합니다'; | |
| const TEXT_NOTMATCH_PASSWORD = '비밀번호가 일치하지 않습니다'; | |
| const TEXT_NOTHAVE_AUTHORITY = '%s권한이 없습니다.'; | |
| const TEXT_GUEST_WRITE_RATE_LIMIT = '잠시 후 다시 등록해 주세요. (1분 이내 연속 등록 제한)'; | |
| const TEXT_UPLOAD_IMPOSSIBLE = '업로드가 불가능합니다'; | |
| const EXCEPTION_CODE_AUTH = 700; | |
| const UPLOAD_DEFAULT_MAX_SIZE = 5; //업로드 최대용량 디플트 값(mb) | |
| if($result['cnt']>0) { | |
| throw new \Exception(__("중복된 게시물을 연속으로 등록할 수 없습니다. \n중복 게시물이 아닌 경우, 잠시 후 다시 등록하시기 바랍니다.")); | |
| } | |
| } | |
| // 비회원(memNo=0) 게시글/답변 연속 등록 제한: 동일 IP 60초 이내 재등록 차단 (제목 무관) | |
| if (in_array($this->req['mode'], ['write', 'reply'], true) && (int) $this->member['memNo'] === 0) { | |
| $remoteAddr = Request::getRemoteAddress(); | |
| $guestBind = []; | |
| $this->db->bind_param_push($guestBind, 's', $remoteAddr); | |
| $guestResult = $this->db->query_fetch("SELECT count(*) as cnt FROM " . DB_BD_ . $this->cfg['bdId'] . " WHERE memNo = 0 AND writerIp = ? AND regDt >= (now() - INTERVAL 60 SECOND) ", $guestBind, false); | |
| if ($guestResult['cnt'] > 0) { | |
| try { | |
| \Logger::channel('board')->warning('[Board] 비회원 연속 등록 제한', ['bdId' => $this->cfg['bdId'], 'writerIp' => $remoteAddr]); | |
| } catch (\Throwable $e) { | |
| } | |
| throw new \Exception(__(self::TEXT_GUEST_WRITE_RATE_LIMIT)); | |
| } | |
| } | |
| return true; | |
| } | |
변경 전BoardPsController.php
| use Component\Member\MemberReport; | |
| use Component\Validator\Validator; | |
| use Framework\Debug\Exception\AlertBackException; | |
| use Framework\ObjectStorage\Service\ImageUploadService; | |
| use GuzzleHttp\Psr7\Query; | |
| use View\Template; | |
| exit; | |
| } catch (\Exception $e) { | |
| throw new AlertBackException($e->getMessage()); | |
| } | |
| break; | |
변경 후BoardPsController.php
| use Component\Member\MemberReport; | |
| use Component\Validator\Validator; | |
| use Framework\Debug\Exception\AlertBackException; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\ObjectStorage\Service\ImageUploadService; | |
| use GuzzleHttp\Psr7\Query; | |
| use View\Template; | |
| exit; | |
| } catch (\Exception $e) { | |
| // 비밀글은 글 상세가 POST로 열리므로 답글 실패 후 뒤로가기 시 양식 재전송 확인 페이지가 노출됨 | |
| $isListReturn = gd_isset($req['gboard']) != 'y' && gd_isset($req['gboard']) != 'r'; | |
| if ($req['mode'] == 'reply' && $isListReturn && isset($boardAct) && $boardAct->cfg['bdSecretFl'] != '2') { | |
| throw new AlertRedirectException($e->getMessage(), 0, null, '../board/list.php?' . $req['returnUrl']); | |
| } | |
| throw new AlertBackException($e->getMessage()); | |
| } | |
| break; | |
변경 전auto_send_config_recipient_section.php
| <div class="ncua-card__body-block-section-wrap"> | |
| <section class="ncua-card__body-block-section"> | |
| <div class="ncua-card__body-title--xs">내용 입력</div> | |
| <div id="sms-message-input-container-<?= $recipient ?>" | |
| data-initial-value="<?= htmlspecialchars($autoSendConfig['SMS']['templateContents'] ?? '', ENT_QUOTES) ?>"> | |
| </div> | |
변경 후auto_send_config_recipient_section.php
| <div class="ncua-card__body-block-section-wrap"> | |
| <section class="ncua-card__body-block-section"> | |
| <div class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="009">내용 입력</div> | |
| <?php /* 제목은 본문이 LMS(90bytes 초과)일 때만 활성 — 토글·카운트는 JS(initMessageModules)가 담당 */ ?> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs is-disabled"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="recipients[<?= $recipient ?>][SMS][templateTitle]" type="text" | |
| value="<?= htmlspecialchars($autoSendConfig['SMS']['templateTitle'] ?? '', ENT_QUOTES) ?>" | |
| placeholder="제목을 입력해 주세요." data-sms-title-input disabled /> | |
| </div> | |
| </div> | |
| </div> | |
| <span class="message-title-count"> | |
| <span data-sms-title-current>0</span>/40 | |
| </span> | |
| </div> | |
| <div id="sms-message-input-container-<?= $recipient ?>" | |
| data-initial-value="<?= htmlspecialchars($autoSendConfig['SMS']['templateContents'] ?? '', ENT_QUOTES) ?>"> | |
| </div> | |
변경 전auto_send_config.php
| if (tabInfo.channel === 'SMS') { | |
| const input = messageInputInstances[recipient]?.SMS; | |
| const smsContent = input ? normalizeNewlines(input.getValue()) : ''; | |
| this.setPreview(section, { content: smsContent || '메시지 내용을 입력하세요.' }); | |
| } else if (tabInfo.channel === 'KAKAO_ALRIM_TALK') { | |
| const tabContent = section.querySelector('[data-tab="KAKAO_ALRIM_TALK"]'); | |
| if (!tabContent) return; | |
| // SMS/LMS 포인트 힌트 업데이트 | |
| const byteLength = smsInput.calculateLength(normalized); | |
| smsInput.setHint(byteLength > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| // 빈 내용일 때 안내문구 숨김 | |
| if (normalized === '') { | |
| const caution = document.querySelector(`#sms-chip-selector-container-${recipient} [data-caution-template]`); | |
| }); | |
| messageInputInstances[recipient].SMS = smsInput; | |
| // 초기 힌트 상태 설정 | |
| const hintEl = smsContainer.querySelector('[data-message-hint]'); | |
| if (hintEl) hintEl.classList.add('destructive'); | |
변경 후auto_send_config.php
| if (tabInfo.channel === 'SMS') { | |
| const input = messageInputInstances[recipient]?.SMS; | |
| const smsContent = input ? normalizeNewlines(input.getValue()) : ''; | |
| const smsTitleInput = section.querySelector('input[data-sms-title-input]'); | |
| const smsTitle = smsTitleInput && !smsTitleInput.disabled ? smsTitleInput.value.replace(/\{[^}]*\}/g, '') : ''; | |
| this.setPreview(section, { title: smsTitle, content: smsContent || '메시지 내용을 입력하세요.' }); | |
| } else if (tabInfo.channel === 'KAKAO_ALRIM_TALK') { | |
| const tabContent = section.querySelector('[data-tab="KAKAO_ALRIM_TALK"]'); | |
| if (!tabContent) return; | |
| // SMS/LMS 포인트 힌트 업데이트 | |
| const byteLength = smsInput.calculateLength(normalized); | |
| smsInput.setHint(byteLength > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setSmsTitleEnabled(byteLength > 90); | |
| // 빈 내용일 때 안내문구 숨김 | |
| if (normalized === '') { | |
| const caution = document.querySelector(`#sms-chip-selector-container-${recipient} [data-caution-template]`); | |
| }); | |
| messageInputInstances[recipient].SMS = smsInput; | |
| // ===== SMS/LMS 제목 — 본문이 LMS(90bytes 초과)일 때만 활성 (모바일 발송과 동일 규칙) ===== | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| const sectionEl = smsContainer.closest('[data-target-type]'); | |
| const smsTitleInput = sectionEl.querySelector('input[data-sms-title-input]'); | |
| const smsTitleCounter = sectionEl.querySelector('[data-sms-title-current]'); | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 제목은 변수 미지원이라 치환자는 공란으로 표기 | |
| const updateSmsTitlePreview = () => { | |
| if (!smsTitleInput) return; | |
| const value = !smsTitleInput.disabled ? smsTitleInput.value.replace(/\{[^}]*\}/g, '') : ''; | |
| PreviewFacade.setPreview(sectionEl, { title: value }); | |
| }; | |
| // 제목 입력 — 이모지 제거, 40bytes 초과분 자동 삭제 (byte 기준은 본문 MessageInput 과 동일) | |
| const handleSmsTitleInput = () => { | |
| if (!smsTitleInput) return; | |
| let value = smsInput.removeEmoji(smsTitleInput.value).value; | |
| value = smsInput.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| if (smsTitleInput.value !== value) { | |
| smsTitleInput.value = value; | |
| } | |
| if (smsTitleCounter) smsTitleCounter.textContent = smsInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| }; | |
| // SMS 로 돌아오면 값은 유지한 채 비활성 | |
| const setSmsTitleEnabled = (enabled) => { | |
| if (!smsTitleInput) return; | |
| smsTitleInput.disabled = !enabled; | |
| smsTitleInput.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| }; | |
| if (smsTitleInput) { | |
| smsTitleInput.addEventListener('input', handleSmsTitleInput); | |
| // 초기 상태: 저장된 본문 byte 기준 활성 여부 + 저장된 제목 카운트 반영 | |
| setSmsTitleEnabled(smsInput.calculateLength(smsInitialValue) > 90); | |
| handleSmsTitleInput(); | |
| } | |
| // 초기 힌트 상태 설정 | |
| const hintEl = smsContainer.querySelector('[data-message-hint]'); | |
| if (hintEl) hintEl.classList.add('destructive'); | |
변경 전crm_recipe_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| const fail = (message, subMessage) => { | |
| NCDSAlert({ message, subMessage, iconType: 'error' }); | |
| $button.prop('disabled', false); | |
| allKeys.includes(MobileMessageReplaceCode.normalizeReplaceKey(key)) ? `{${key}}` : match); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview?.setContent(alternativeContents); | |
| } | |
| sendClickLog('send'); | |
변경 후crm_recipe_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 제목 40byte 초과(C4-2)는 미해소 에러라 재표기 | |
| if (typeof refreshOverSmsTitleState === 'function') { | |
| refreshOverSmsTitleState(); | |
| } | |
| const fail = (message, subMessage) => { | |
| NCDSAlert({ message, subMessage, iconType: 'error' }); | |
| $button.prop('disabled', false); | |
| allKeys.includes(MobileMessageReplaceCode.normalizeReplaceKey(key)) ? `{${key}}` : match); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview?.setContent(alternativeContents); | |
| if (typeof copyMainTitleToAlternativeSmsTitle === 'function') { | |
| copyMainTitleToAlternativeSmsTitle(); | |
| } | |
| } | |
| sendClickLog('send'); | |
변경 전layer_preview_auto_send.php
| <?php if ($channelKey === 'SMS'): ?> | |
| <!-- SMS 미리보기 --> | |
| <section data-component="sms-message-preview" class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"><?= nl2br(htmlspecialchars($templateContents)) ?></div> | |
| </section> | |
| <?php elseif ($channelKey === 'KAKAO_ALRIM_TALK'): | |
변경 후layer_preview_auto_send.php
| <?php if ($channelKey === 'SMS'): ?> | |
| <!-- SMS 미리보기 --> | |
| <section data-component="sms-message-preview" class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($channelData['templateTitle'] ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= htmlspecialchars($channelData['templateTitle']) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(htmlspecialchars($templateContents)) ?> | |
| </div> | |
| </section> | |
| <?php elseif ($channelKey === 'KAKAO_ALRIM_TALK'): | |
변경 전layer_template_contents_sms.php
| <!-- SMS/LMS --> | |
| <section class="mobile-preview mobile-preview--sms layer-preview-contents--sms"> | |
| <div class="ncua-prev"><?= nl2br(htmlspecialchars($smsData?->getContents() ?? '')) ?></div> | |
| </section> | |
변경 후layer_template_contents_sms.php
| <!-- SMS/LMS --> | |
| <section class="mobile-preview mobile-preview--sms layer-preview-contents--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($smsData?->getMessageTitle() ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= htmlspecialchars($smsData->getMessageTitle()) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(htmlspecialchars($smsData?->getContents() ?? '')) ?> | |
| </div> | |
| </section> | |
변경 전message_template_register.php
| element.querySelectorAll('input, textarea, select').forEach(field => { | |
| // 체크박스로 제어되는 textarea는 제외 | |
| if (field.id === 'channelAddTextarea' || field.id === 'extraInfoTextarea') return; | |
| // 수정/복제 모드에서 발송수단, 제공사는 disabled 유지 | |
| if (field.name === 'sendMethod' || field.name === 'provider') return; | |
| field.disabled = !isVisible; | |
| }); | |
| }; | |
| /** | |
| * SMS 바이트 수에 따라 SMS/LMS 포인트 차감 힌트 텍스트 변경 | |
| */ | |
| } else { | |
| smsMessageInput.setHint(''); | |
| } | |
| }; | |
| /** | |
| } | |
| }); | |
| // 수정/복제 모드: initialValue 기준으로 SMS/LMS 힌트 초기화 | |
| updateSmsMessageHint(initialData.smsContent || ''); | |
| const smsVariableSelector = GodoUIModule.render({ | |
| type: 'ChipSelector', | |
| target: '#sms-variable-selector-container', | |
| document.querySelectorAll('#sms-message-input-container .ncua-input, #kakao-message-input-container .ncua-input, #myapp-message-input-container .ncua-input') | |
| .forEach(el => el.setAttribute('data-show-hint-text', 'true')); | |
| let templatePreview = null; | |
| window.addEventListener('crmPreviewLoaded', function() { | |
| const currentSendMethod = document.querySelector('input[name="sendMethod"]:checked')?.value || 'sms'; | |
| const sendTypeMap = { 'sms': 'SMS', 'kakao': 'ALIMTALK', 'myapp': 'MYAPP' }; | |
| } | |
| templatePreview.setContent(displayValue); | |
| } | |
| }; | |
| // 변수 변환 체크박스 이벤트 리스너 (CrmPreview 체크박스 사용) | |
| formData.append('templateCategory', document.querySelector('input[name="templateCategory"]:checked')?.value || ''); | |
| formData.append('templateTitle', document.querySelector('input[name="templateTitle"]')?.value || ''); | |
| formData.append('templateMessageContent', escapeLineBreaks(document.querySelector('textarea[name="smsMessageInput"]')?.value || '')); | |
| submitForm(); | |
| } else if (sendMethod === 'kakao') { | |
변경 후message_template_register.php
| element.querySelectorAll('input, textarea, select').forEach(field => { | |
| // 체크박스로 제어되는 textarea는 제외 | |
| if (field.id === 'channelAddTextarea' || field.id === 'extraInfoTextarea') return; | |
| // SMS 제목은 본문 LMS 여부로 활성 상태를 관리하므로 제외 | |
| if (field.name === 'templateMessageTitle') return; | |
| // 수정/복제 모드에서 발송수단, 제공사는 disabled 유지 | |
| if (field.name === 'sendMethod' || field.name === 'provider') return; | |
| field.disabled = !isVisible; | |
| }); | |
| }; | |
| // crmPreviewLoaded 이후 생성 — 선언보다 먼저 실행되는 초기화 코드(제목 미리보기 등)에서 참조하므로 여기서 선언 | |
| let templatePreview = null; | |
| /** | |
| * SMS/LMS 메시지 제목 — 본문이 LMS(90bytes 초과)일 때만 활성 (모바일 발송과 동일 정책) | |
| */ | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| const getSmsTitleInput = () => document.querySelector('input[name="templateMessageTitle"]'); | |
| const isSmsTitleEnabled = () => { | |
| const input = getSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| }; | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 제목은 변수 미지원이라 치환자는 공란으로 표기 | |
| const updateSmsTitlePreview = () => { | |
| if (!templatePreview) return; | |
| const value = isSmsTitleEnabled() ? getSmsTitleInput().value.replace(/\{[^}]*\}/g, '') : ''; | |
| templatePreview.setTitle(value); | |
| }; | |
| // SMS 로 돌아오면 값은 유지한 채 비활성 | |
| const setSmsTitleEnabled = (enabled) => { | |
| const input = getSmsTitleInput(); | |
| if (!input) return; | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| }; | |
| // 제목 입력 — 이모지 제거, 40bytes 초과분 자동 삭제 (byte 기준은 본문 MessageInput 과 동일) | |
| const handleSmsTitleInput = () => { | |
| const input = getSmsTitleInput(); | |
| let value = smsMessageInput.removeEmoji(input.value).value; | |
| value = smsMessageInput.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| if (input.value !== value) { | |
| input.value = value; | |
| } | |
| document.querySelector('[data-sms-title-current]').textContent = smsMessageInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| }; | |
| /** | |
| * SMS 바이트 수에 따라 SMS/LMS 포인트 차감 힌트 텍스트 변경 | |
| */ | |
| } else { | |
| smsMessageInput.setHint(''); | |
| } | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setSmsTitleEnabled(currentBytes > 90); | |
| }; | |
| /** | |
| } | |
| }); | |
| // 수정/복제 모드: initialValue 기준으로 SMS/LMS 힌트 초기화 (제목 활성 상태 포함) | |
| updateSmsMessageHint(initialData.smsContent || ''); | |
| // 제목 입력 이벤트 + 초기 카운터 반영 (수정/복제 모드: 저장된 제목) | |
| getSmsTitleInput().addEventListener('input', handleSmsTitleInput); | |
| handleSmsTitleInput(); | |
| const smsVariableSelector = GodoUIModule.render({ | |
| type: 'ChipSelector', | |
| target: '#sms-variable-selector-container', | |
| document.querySelectorAll('#sms-message-input-container .ncua-input, #kakao-message-input-container .ncua-input, #myapp-message-input-container .ncua-input') | |
| .forEach(el => el.setAttribute('data-show-hint-text', 'true')); | |
| window.addEventListener('crmPreviewLoaded', function() { | |
| const currentSendMethod = document.querySelector('input[name="sendMethod"]:checked')?.value || 'sms'; | |
| const sendTypeMap = { 'sms': 'SMS', 'kakao': 'ALIMTALK', 'myapp': 'MYAPP' }; | |
| } | |
| templatePreview.setContent(displayValue); | |
| } | |
| if (sendMethod === 'sms') { | |
| updateSmsTitlePreview(); | |
| } | |
| }; | |
| // 변수 변환 체크박스 이벤트 리스너 (CrmPreview 체크박스 사용) | |
| formData.append('templateCategory', document.querySelector('input[name="templateCategory"]:checked')?.value || ''); | |
| formData.append('templateTitle', document.querySelector('input[name="templateTitle"]')?.value || ''); | |
| formData.append('templateMessageContent', escapeLineBreaks(document.querySelector('textarea[name="smsMessageInput"]')?.value || '')); | |
| // 제목은 SMS/LMS 여부와 무관하게 입력값이 있으면 함께 저장 (모바일 발송 템플릿 저장과 동일) | |
| formData.append('templateMessageTitle', getSmsTitleInput()?.value || ''); | |
| submitForm(); | |
| } else if (sendMethod === 'kakao') { | |
변경 전template_contents_sms.php
| <!-- 본문 입력: SMS 바이트형 --> | |
| <div class="message-content sms-byte-mode" data-component="message-content"> | |
| <div class="ncua-card__body-title-wrap ncua-required"> | |
| <p class="ncua-card__body-title--xs">본문 입력</p> | |
| </div> | |
| <div id="sms-message-input-container" class="message-input-container"></div> | |
| </div> | |
| <div class="ncua-accordion__content has-dot"> | |
| <ul> | |
| <li>URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" target="_blank" class="ncua-link-underline">바로가기</a></li> | |
| </ul> | |
| </div> | |
| </details> | |
변경 후template_contents_sms.php
| <!-- 본문 입력: SMS 바이트형 --> | |
| <div class="message-content sms-byte-mode" data-component="message-content"> | |
| <div class="ncua-card__body-title-wrap ncua-required"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="008">본문 입력</p> | |
| </div> | |
| <?php /* 제목은 본문이 LMS(90bytes 초과)일 때만 활성 — 토글은 JS(setSmsTitleEnabled)가 담당 */ ?> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs is-disabled"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="templateMessageTitle" type="text" value="<?= htmlspecialchars($response->getSms()?->getMessageTitle() ?? '') ?>" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| </div> | |
| <span class="message-title-count"> | |
| <span data-sms-title-current>0</span>/40 | |
| </span> | |
| </div> | |
| <div id="sms-message-input-container" class="message-input-container"></div> | |
| </div> | |
| <div class="ncua-accordion__content has-dot"> | |
| <ul> | |
| <li>URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" target="_blank" class="ncua-link-underline">바로가기</a></li> | |
| <li>제목은 LMS 발송 시에만 적용되는 선택 입력 항목으로, 미입력 시에는 ‘제목 없음’으로 발송되며 SMS 발송 시에는 포함되지 않습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
변경 전layer_member_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 후layer_member_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?php if (($smsHistory->getTitle() ?? '') !== ''): ?><span style="display: block;"><?= gd_htmlspecialchars($smsHistory->getTitle()) ?></span><?php endif; ?><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 전layer_sms_contents.php
| <div class="mobile-preview-wrap"> | |
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"><?= nl2br(gd_htmlspecialchars_stripslashes($content)) ?></div> | |
| </section> | |
| </div> | |
변경 후layer_sms_contents.php
| <div class="mobile-preview-wrap"> | |
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($title ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= gd_htmlspecialchars_stripslashes($title) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(gd_htmlspecialchars_stripslashes($content)) ?> | |
| </div> | |
| </section> | |
| </div> | |
변경 전layer_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 후layer_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?php if (($smsHistory->getTitle() ?? '') !== ''): ?><span style="display: block;"><?= gd_htmlspecialchars($smsHistory->getTitle()) ?></span><?php endif; ?><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 전layer_kakao_alimtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| setDefaultPreview(['ALIMTALK_TEXT', 'ALTERNATIVE_TEXT']); | |
| } | |
| </script> | |
변경 후layer_kakao_alimtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| copyMainTitleToAlternativeSmsTitle(); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| setDefaultPreview(['ALIMTALK_TEXT', 'ALTERNATIVE_TEXT']); | |
| } | |
| </script> | |
| <script type="text/javascript"> | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙·디자인은 SMS/친구톡 대체와 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return document.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| document.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input) return; | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| // 메인 제목 → 대체 제목 매핑 — 알림톡은 강조표기형(templateTitle)만 매핑 대상 | |
| function copyMainTitleToAlternativeSmsTitle() { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input || getActivatedSendMethod() !== 'ALIMTALK') return; | |
| input.value = getSelectedKakaoAlimtalkTemplate()?.templateTitle ?? ''; | |
| // 본문 카피 직후엔 입력 이벤트가 없어 활성 상태가 갱신되지 않는다 — 여기서 다시 잡아야 payload 에 실린다 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| </script> | |
변경 전layer_kakao_friendtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="js-replace-code send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| updateCampaignTypeComponent(radio.value); | |
| updateDefaultPreview(radio.value); | |
| applyFriendtalkRecipeDefaults(radio.value); | |
| }); | |
| }); | |
| } | |
| }); | |
| kakaoFriendtalkTabSection.querySelector('input[name="friendtalkCampaignHeader"]').addEventListener('input', function(e) { | |
| window.preview.setTitle(resolveReplaceCode(e.target.value)); | |
| if (e.target.value === '') { | |
| const initialTextContent = <?= json_encode($initialTextContent ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeMessage = <?= json_encode($initialAlternativeMessage ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (isRecipeContext) { | |
| const wideItemPointHint = kakaoFriendtalkTabSection.querySelector('.js-wide-item-point-hint'); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| applyFriendtalkRecipeDefaults(getCampaignMessageType()); | |
| } | |
| updateItemListPreview(); | |
| } | |
| // 친구톡 아이템 이미지 업로드 초기화 | |
| function initItemImageFileInput(containerId, itemKey, isFirst = false) { | |
| const container = document.getElementById(containerId); | |
변경 후layer_kakao_friendtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="js-replace-code send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| updateCampaignTypeComponent(radio.value); | |
| updateDefaultPreview(radio.value); | |
| applyFriendtalkRecipeDefaults(radio.value); | |
| // 유형에 따라 대체 지원 여부가 바뀌므로 제목 활성 상태를 다시 평가 (초기 change 는 대체 입력 생성 전이라 건너뜀) | |
| if (window.alternativeMessageInput) { | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| } | |
| }); | |
| }); | |
| } | |
| }); | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| kakaoFriendtalkTabSection.querySelector('input[name="friendtalkCampaignHeader"]').addEventListener('input', function(e) { | |
| window.preview.setTitle(resolveReplaceCode(e.target.value)); | |
| if (e.target.value === '') { | |
| const initialTextContent = <?= json_encode($initialTextContent ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeMessage = <?= json_encode($initialAlternativeMessage ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeTitle = <?= json_encode($initialAlternativeTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (isRecipeContext) { | |
| const wideItemPointHint = kakaoFriendtalkTabSection.querySelector('.js-wide-item-point-hint'); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| // 레시피 기본 대체 제목 prefill — 대체 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성 (메인 SMS 레이어와 동일) | |
| if (initialAlternativeTitle !== '') { | |
| getAlternativeSmsTitleInput().value = initialAlternativeTitle; | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(initialAlternativeMessage) > 90); | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| applyFriendtalkRecipeDefaults(getCampaignMessageType()); | |
| } | |
| updateItemListPreview(); | |
| } | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙은 SMS 레이어의 제목과 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return kakaoFriendtalkTabSection.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| kakaoFriendtalkTabSection.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| // 친구톡 아이템 이미지 업로드 초기화 | |
| function initItemImageFileInput(containerId, itemKey, isFirst = false) { | |
| const container = document.getElementById(containerId); | |
변경 전layer_mobile_send_save_sms_template.php
| <div class="modal-dialog__content layer-save-as-template"> | |
| <input type="hidden" id="templateContents" value="<?= htmlspecialchars($contents, ENT_QUOTES) ?>" /> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <tbody> | |
| mode: 'save', | |
| category: category.value, | |
| subject: subject.value.trim(), | |
| contents: contents.value | |
| }, function(response) { | |
| if (response.success) { | |
| NCDSToast({ message: '저장되었습니다.', color: 'success' }); | |
변경 후layer_mobile_send_save_sms_template.php
| <div class="modal-dialog__content layer-save-as-template"> | |
| <input type="hidden" id="templateContents" value="<?= htmlspecialchars($contents, ENT_QUOTES) ?>" /> | |
| <input type="hidden" id="templateMessageTitle" value="<?= htmlspecialchars($messageTitle ?? '', ENT_QUOTES) ?>" /> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <tbody> | |
| mode: 'save', | |
| category: category.value, | |
| subject: subject.value.trim(), | |
| contents: contents.value, | |
| messageTitle: document.querySelector('#templateMessageTitle').value | |
| }, function(response) { | |
| if (response.success) { | |
| NCDSToast({ message: '저장되었습니다.', color: 'success' }); | |
변경 전layer_mobile_send_sms_template.php
| } | |
| } | |
| function applyTemplateSmsContents(contents) { | |
| const convertedContents = contents | |
| .replace(/\\r\\n/g, '\n') | |
| .replace(/\\n/g, '\n'); | |
| setTemplate(convertedContents); | |
| } | |
| document.getElementById('btnSearch').addEventListener('click', function() { | |
| return; | |
| } | |
| applyTemplateSmsContents(selected.dataset.contents); | |
| layer_close(); | |
| }); | |
변경 후layer_mobile_send_sms_template.php
| } | |
| } | |
| function applyTemplateSmsContents(contents, messageTitle = '') { | |
| const convertedContents = contents | |
| .replace(/\\r\\n/g, '\n') | |
| .replace(/\\n/g, '\n'); | |
| setTemplate(convertedContents, messageTitle); | |
| } | |
| document.getElementById('btnSearch').addEventListener('click', function() { | |
| return; | |
| } | |
| applyTemplateSmsContents(selected.dataset.contents, selected.dataset.messageTitle ?? ''); | |
| layer_close(); | |
| }); | |
변경 전layer_mobile_send_sms_template_result.php
| <div class="ncua-align-center"> | |
| <label class="ncua-radio-field ncua-radio-field--xs"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="template" value="<?= $template['sno'] ?>" data-contents="<?= htmlspecialchars($template['contents'], ENT_QUOTES) ?>"/> | |
| </span> | |
| </label> | |
| </div> | |
| </td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['subject'] ?? ''))) ?></div></td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['contents'] ?? ''))) ?></div></td> | |
| </tr> | |
| <?php endforeach; ?> | |
| <?php endif; ?> | |
변경 후layer_mobile_send_sms_template_result.php
| <div class="ncua-align-center"> | |
| <label class="ncua-radio-field ncua-radio-field--xs"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="template" value="<?= $template['sno'] ?>" data-contents="<?= htmlspecialchars($template['contents'], ENT_QUOTES) ?>" data-message-title="<?= htmlspecialchars($template['messageTitle'] ?? '', ENT_QUOTES) ?>"/> | |
| </span> | |
| </label> | |
| </div> | |
| </td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['subject'] ?? ''))) ?></div></td> | |
| <td> | |
| <?php /* td > div 가 flex 컨테이너라 제목·내용을 하나의 블록으로 감싸야 분리되지 않음 */ ?> | |
| <div> | |
| <div><?php if (($template['messageTitle'] ?? '') !== ''): ?><strong style="display: block;"><?= htmlspecialchars($template['messageTitle']) ?></strong><?php endif; ?><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['contents'] ?? ''))) ?></div> | |
| </div> | |
| </td> | |
| </tr> | |
| <?php endforeach; ?> | |
| <?php endif; ?> | |
변경 전layer_myapp_push_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| window.alternativePreview.setContent(resolveReplaceCode(initialAlternativeMessage, false)); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| syncMyappTitlePreview(initialMyappTitle); | |
| syncMyappMessagePreview(initialMyappMessage); | |
| } | |
| }); | |
| }); | |
| </script> | |
변경 후layer_myapp_push_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| copyMainTitleToAlternativeSmsTitle(); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| window.alternativePreview.setContent(resolveReplaceCode(initialAlternativeMessage, false)); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| syncMyappTitlePreview(initialMyappTitle); | |
| syncMyappMessagePreview(initialMyappMessage); | |
| } | |
| }); | |
| }); | |
| </script> | |
| <script type="text/javascript"> | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙·디자인은 SMS/친구톡 대체와 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return document.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| document.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input) return; | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| function copyMainTitleToAlternativeSmsTitle() { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input || getActivatedSendMethod() !== 'MYAPP') return; | |
| input.value = document.querySelector('input[name="myappTitle"]')?.value ?? ''; | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| // 레시피 기본 대체 제목 prefill — 대체 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성. | |
| // 제목 접근자가 이 블록에 선언돼 있어(앞 블록의 초기화 시점엔 미정의) 여기서 수행한다. | |
| (function () { | |
| const initialAlternativeTitle = <?= json_encode($initialAlternativeTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (initialAlternativeTitle === '') return; | |
| getAlternativeSmsTitleInput().value = initialAlternativeTitle; | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| handleAlternativeSmsTitleInput(); | |
| })(); | |
| </script> | |
변경 전layer_send_method_setting.php
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 본문 갱신으로 SMS/LMS 판정이 끝난 뒤, LMS(제목 활성)면 제목에도 (광고) 삽입 — 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.disabled && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| return /^https?:\/\//.test(string); | |
| } | |
| function addAdText(messageContainer, previewContainer) { | |
| const content = '(광고)\n' + messageContainer.getValue() + '\n' + smsRejectText; | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| } | |
| function removeAdText(messageContainer, previewContainer) { | |
| let content = messageContainer.getValue(); | |
| content = content.replace(/^\(광고\)\n?/, ''); | |
| const escapedRejectText = smsRejectText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| } | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| } | |
| /** | |
변경 후layer_send_method_setting.php
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 제목에도 (광고) 삽입 — 제목 영역이 비활성(SMS)이어도 삽입한다(레거시 동작과 동일). 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| return /^https?:\/\//.test(string); | |
| } | |
| // LMS 제목 최대 byte — 직접 입력 초과는 절삭(C1-1), (광고) 삽입 초과는 에러 유지(C4-2) | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| // 제목 인풋과 같은 탭의 '광고성 문구 추가' 체크박스 | |
| function getAdCheckboxForTitle(titleInput) { | |
| for (let node = titleInput.parentElement; node; node = node.parentElement) { | |
| const checkbox = node.querySelector('input[name="use080Reject"]'); | |
| if (checkbox) return checkbox; | |
| } | |
| return null; | |
| } | |
| // 초과 에러 표기 — destructive 로 테두리·byte 카운터가 함께 빨간색이 된다 | |
| function setSmsTitleOverState(titleInput, isOver) { | |
| titleInput.classList.toggle('js-title-over', isOver); | |
| if (isOver) { | |
| NCDSValidator.highlight(titleInput); | |
| } else { | |
| NCDSValidator.unhighlight(titleInput); | |
| } | |
| } | |
| // 제목 byte 규칙 적용(이모지 제거 포함) 후 최종 값 반환 | |
| function applySmsTitleByteRule(titleInput, messageInputModule) { | |
| let value = messageInputModule.removeEmoji(titleInput.value).value; | |
| const isOver = messageInputModule.getByteLength(value) > SMS_TITLE_MAX_BYTES; | |
| // addAdText 가 (광고) 삽입 시에만 세우는 1회성 플래그 (사용자 타이핑과 구분) | |
| const adInserted = titleInput.dataset.titleAdInsert === '1'; | |
| const base = titleInput.dataset.titleOverBase; | |
| let caret = null; | |
| delete titleInput.dataset.titleAdInsert; | |
| if (isOver && (adInserted || base !== undefined)) { | |
| // C4-2 — 절삭하지 않는다. 초과 상태에서는 늘리는 입력만 되돌리고 삭제는 허용 | |
| if (!adInserted && base !== undefined && messageInputModule.getByteLength(value) > messageInputModule.getByteLength(base)) { | |
| // 되돌린 만큼 커서를 입력 직전 위치로 복원 | |
| caret = Math.max(0, (titleInput.selectionStart ?? value.length) - (value.length - base.length)); | |
| value = base; | |
| } | |
| titleInput.dataset.titleOverBase = value; | |
| setSmsTitleOverState(titleInput, true); | |
| } else { | |
| // C1-1 — 직접 입력 초과는 (광고) 체크 여부와 무관하게 자동 절삭 | |
| value = messageInputModule.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| delete titleInput.dataset.titleOverBase; | |
| setSmsTitleOverState(titleInput, false); | |
| } | |
| if (titleInput.value !== value) { | |
| titleInput.value = value; | |
| if (caret !== null) { | |
| titleInput.setSelectionRange(caret, caret); | |
| } | |
| } | |
| return value; | |
| } | |
| // 발송 버튼의 .destructive 일괄 초기화(mobile_send.php) 후 미해소 에러 재표기 | |
| function refreshOverSmsTitleState() { | |
| document.querySelectorAll('input[name="smsTitle"], input[name="alternativeSmsTitle"]') | |
| .forEach(input => { | |
| if (input.classList.contains('js-title-over')) { | |
| setSmsTitleOverState(input, true); | |
| } | |
| }); | |
| } | |
| // 초과 제목이 숨은 탭에 있으면 그 탭으로 전환해 에러 표시를 보이게 한다 | |
| function revealSmsTitleInput(input) { | |
| const target = input.closest('.send-method-component')?.dataset.target; | |
| const tabButton = target | |
| ? document.querySelector(`.ncua-tab-button[data-send-tab-type="${target}"]`) | |
| : null; | |
| if (tabButton && !tabButton.classList.contains('is-active')) { | |
| tabButton.click(); | |
| } | |
| NCDSValidator.highlight(input); | |
| input.focus(); | |
| input.scrollIntoView({ block: 'center' }); | |
| } | |
| // 발송 차단 검사용 — payload 에 실리는 기준(disabled)과 동일하게 판정한다. | |
| // 가시성으로 거르면 탭을 옮겨 숨겨진 제목이 검사를 건너뛴 채 전송된다. | |
| function findOverSmsTitleInput() { | |
| const titleInputs = document.querySelectorAll('input[name="smsTitle"], input[name="alternativeSmsTitle"]'); | |
| return Array.from(titleInputs) | |
| .find(input => !input.disabled && input.classList.contains('js-title-over')) ?? null; | |
| } | |
| function addAdText(messageContainer, previewContainer) { | |
| // 본문은 SMS/LMS 공통으로 (광고) 삽입 | |
| const content = '(광고)\n' + messageContainer.getValue() + '\n' + smsRejectText; | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 본문 갱신으로 SMS/LMS 판정이 끝난 뒤, LMS(제목 활성)면 제목에도 (광고) 삽입 — 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.disabled && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| // 초과했다면 해당 영역으로 포커싱 | |
| if (titleInput.classList.contains('js-title-over')) { | |
| titleInput.focus(); | |
| } | |
| } | |
| } | |
| function removeAdText(messageContainer, previewContainer) { | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = titleInput.value.replace(/^\(광고\)/, ''); | |
| titleInput.dispatchEvent(new Event('input')); | |
| } | |
| let content = messageContainer.getValue(); | |
| content = content.replace(/^\(광고\)\n?/, ''); | |
| const escapedRejectText = smsRejectText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| } | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| } | |
| // 광고 문구가 들어갈 제목 인풋 — 대체 메시지 컨테이너면 대체 제목, 아니면 메인 제목 | |
| function resolveAdTitleInput(messageContainer) { | |
| return messageContainer === window.alternativeMessageInput | |
| ? document.querySelector('input[name="alternativeSmsTitle"]') | |
| : document.querySelector('input[name="smsTitle"]'); | |
| } | |
| // setValue 는 MessageInput 의 onInput 콜백을 부르지 않으므로, 본문 변경 후 | |
| // SMS/LMS 판단(제목 활성 토글·힌트 갱신)이 다시 돌도록 input 이벤트를 수동 발행 | |
| function dispatchMessageContentInput(messageContainer) { | |
| const name = messageContainer === window.alternativeMessageInput ? 'messageAlternativeContent' : 'messageContent'; | |
| document.querySelector(`textarea[name="${name}"]`)?.dispatchEvent(new Event('input')); | |
| } | |
| /** | |
변경 전layer_sms_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| <div class="tab-content-wrap"> | |
| <div class="message-content"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| </div> | |
| <div id="messageContentContainer"></div> | |
| </div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| $(document).ready(function () { | |
| initializeSmsContentSettingSectionEvents(); | |
| initializeSmsContentSettingSectionElement(); | |
| }); | |
| function initializeSmsContentSettingSectionEvents() { | |
| }); | |
| return; | |
| } | |
| const smsData = [{ name: "contents", value: message }]; | |
| $.post('./mobile_send/layer_mobile_send_save_sms_template.php', smsData, function (data) { | |
| ncds_layer_popup({message: data, title: '템플릿으로 저장<div class="modal-title-description">작성한 내용을 저장할 카테고리와 제목을 선택하여 주시기 바랍니다.</div>', size: 'wide-sm'}); | |
| }); | |
| removeAdText(window.messageInput, window.preview); | |
| } | |
| }); | |
| } | |
| // 칩 버튼 생성 함수 | |
| syncSmsPreviewAndHint(initialMessage); | |
| const recipientType = document.querySelector('input[name="recipientType"]:checked')?.value; | |
| if (['EXCEL_UPLOAD', 'DIRECT'].includes(recipientType)) { | |
| smsSettingSection.querySelector('.js-replace-code').classList.add('display-none'); | |
| } else { | |
| window.messageInput.setHint(window.messageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| function setTemplate(message) { | |
| smsSettingSection.querySelector('input[name="use080Reject"]').checked = false; | |
| // 메시지 적용 | |
| window.messageInput.setValue(''); | |
| window.messageInput.insertText(message); | |
| // 템플릿 불러오기 안내문구 | |
| smsSettingSection.querySelector('#useTemplateCaution').hidden = false; | |
| } | |
| shortLinkInput.value = ''; | |
| smsSettingSection.querySelector('[data-role="chip-container"]').innerHTML = ''; | |
| window.messageInput.setValue(''); | |
| window.preview.reset(); | |
| const isImpossibleAddShortLink = document.querySelectorAll(`.chip-button[data-send-tab-type="${getActivatedSendTabType()}"]`).length > 4; | |
변경 후layer_sms_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| <div class="tab-content-wrap"> | |
| <div class="message-content"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="smsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentContainer"></div> | |
| </div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| $(document).ready(function () { | |
| initializeSmsContentSettingSectionEvents(); | |
| // CrmPreview(crm-preview.js)는 loader 가 비동기 로드하므로, 준비 전에 element 를 초기화하면 | |
| // MessagePreview 렌더가 null 을 반환해 window.preview 가 null 이 되고, 이후 제목 기본값 prefill· | |
| // LMS 제목 활성화까지 중단된다(레시피 iframe 로드 레이스). → CrmPreview 준비 후 element 초기화. | |
| let isElementInitialized = false; | |
| const runElementInit = function () { | |
| if (isElementInitialized) { | |
| return; | |
| } | |
| isElementInitialized = true; | |
| initializeSmsContentSettingSectionElement(); | |
| }; | |
| // crmPreviewLoaded 가 ready 이전에 이미 발생했을 수 있으므로(캐시 히트 등) 리스너를 먼저 등록하고, | |
| // 준비 완료 상태면 즉시 실행한다(중복 실행은 isElementInitialized 가드로 방지). | |
| window.addEventListener('crmPreviewLoaded', runElementInit); | |
| if (typeof CrmPreview !== 'undefined' && typeof GodoUIModule !== 'undefined') { | |
| runElementInit(); | |
| } | |
| }); | |
| function initializeSmsContentSettingSectionEvents() { | |
| }); | |
| return; | |
| } | |
| // 제목은 SMS/LMS 여부와 무관하게 입력값이 있으면 함께 저장 | |
| const smsData = [ | |
| { name: "contents", value: message }, | |
| { name: "messageTitle", value: getSmsTitleInput().value } | |
| ]; | |
| $.post('./mobile_send/layer_mobile_send_save_sms_template.php', smsData, function (data) { | |
| ncds_layer_popup({message: data, title: '템플릿으로 저장<div class="modal-title-description">작성한 내용을 저장할 카테고리와 제목을 선택하여 주시기 바랍니다.</div>', size: 'wide-sm'}); | |
| }); | |
| removeAdText(window.messageInput, window.preview); | |
| } | |
| }); | |
| getSmsTitleInput().addEventListener('input', handleSmsTitleInput); | |
| } | |
| function getSmsTitleInput() { | |
| return smsSettingSection.querySelector('input[name="smsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleSmsTitleInput() { | |
| const input = getSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.messageInput); | |
| smsSettingSection.querySelector('[data-sms-title-current]').textContent = window.messageInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| } | |
| // 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setSmsTitleEnabled(enabled) { | |
| const input = getSmsTitleInput(); | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| } | |
| function isSmsTitleEnabled() { | |
| const input = getSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateSmsTitlePreview() { | |
| window.preview.setTitle(isSmsTitleEnabled() ? stripTitleReplaceCodes(getSmsTitleInput().value) : ''); | |
| } | |
| // 칩 버튼 생성 함수 | |
| syncSmsPreviewAndHint(initialMessage); | |
| // 레시피 기본 제목 prefill — 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성 (setTemplate 패턴) | |
| const initialTitle = <?= json_encode($initialTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (initialTitle !== '') { | |
| getSmsTitleInput().value = initialTitle; | |
| handleSmsTitleInput(); | |
| } | |
| const recipientType = document.querySelector('input[name="recipientType"]:checked')?.value; | |
| if (['EXCEL_UPLOAD', 'DIRECT'].includes(recipientType)) { | |
| smsSettingSection.querySelector('.js-replace-code').classList.add('display-none'); | |
| } else { | |
| window.messageInput.setHint(window.messageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 (#15092) | |
| setSmsTitleEnabled(window.messageInput.calculateLength(input) > 90); | |
| } | |
| function setTemplate(message, messageTitle = '') { | |
| smsSettingSection.querySelector('input[name="use080Reject"]').checked = false; | |
| // 메시지 적용 (insertText 가 onInput 을 호출해 SMS/LMS 판단·제목 활성 토글이 함께 갱신됨) | |
| window.messageInput.setValue(''); | |
| window.messageInput.insertText(message); | |
| // 저장된 메시지 제목 복원 — SMS 상태면 값만 유지한 채 비활성으로 노출됨 | |
| const titleInput = getSmsTitleInput(); | |
| titleInput.value = messageTitle ?? ''; | |
| handleSmsTitleInput(); | |
| // 템플릿 불러오기 안내문구 | |
| smsSettingSection.querySelector('#useTemplateCaution').hidden = false; | |
| } | |
| shortLinkInput.value = ''; | |
| smsSettingSection.querySelector('[data-role="chip-container"]').innerHTML = ''; | |
| window.messageInput.setValue(''); | |
| const titleInput = getSmsTitleInput(); | |
| titleInput.value = ''; | |
| setSmsTitleOverState(titleInput, false); // 40byte 초과 에러 표기까지 함께 해제 | |
| setSmsTitleEnabled(false); | |
| smsSettingSection.querySelector('[data-sms-title-current]').textContent = '0'; | |
| window.preview.reset(); | |
| const isImpossibleAddShortLink = document.querySelectorAll(`.chip-button[data-send-tab-type="${getActivatedSendTabType()}"]`).length > 4; | |
변경 전mobile_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 발신번호 검증 | |
| if (!messageConfig.hasCallNumber) { | |
| NCDSAlert({message: '발신번호가 없어 발송할 수 없습니다.', subMessage: '설정에서 발신번호 등록 후 발송 시도를 해주세요.', iconType: 'error'}); | |
| }); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview.setContent(alternativeContents); | |
| } | |
| } | |
변경 후mobile_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 제목 40byte 초과(C4-2)는 미해소 에러라 재표기 | |
| if (typeof refreshOverSmsTitleState === 'function') { | |
| refreshOverSmsTitleState(); | |
| } | |
| // 발신번호 검증 | |
| if (!messageConfig.hasCallNumber) { | |
| NCDSAlert({message: '발신번호가 없어 발송할 수 없습니다.', subMessage: '설정에서 발신번호 등록 후 발송 시도를 해주세요.', iconType: 'error'}); | |
| }); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview.setContent(alternativeContents); | |
| if (typeof copyMainTitleToAlternativeSmsTitle === 'function') { | |
| copyMainTitleToAlternativeSmsTitle(); | |
| } | |
| } | |
| } | |
변경 전layer_preview_mobile_send_alternative.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev alternative-contents-preview" style="white-space: pre-wrap;"><?= $alternativeContents ?></div> | |
| </section> | |
| <script> | |
| const alternativeSmsPreview = document.querySelector('.alternative-contents-preview'); | |
| $(document).ready(() => { | |
| alternativeSmsPreview.textContent = resolveReplaceCodeForPreview(alternativeSmsPreview.textContent); | |
| }) | |
| </script> | |
변경 후layer_preview_mobile_send_alternative.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <?php /* pre-wrap 은 본문에만 — 말풍선에 걸면 템플릿 마크업의 공백·줄바꿈까지 렌더링됨 */ ?> | |
| <div class="ncua-prev"> | |
| <?php if (($alternativeTitle ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview alternative-title-preview"><?= gd_htmlspecialchars($alternativeTitle) ?></div> | |
| <?php endif; ?> | |
| <div class="alternative-contents-preview" style="white-space: pre-wrap;"><?= $alternativeContents ?></div> | |
| </div> | |
| </section> | |
| <script> | |
| const alternativeSmsPreview = document.querySelector('.alternative-contents-preview'); | |
| $(document).ready(() => { | |
| alternativeSmsPreview.textContent = resolveReplaceCodeForPreview(alternativeSmsPreview.textContent); | |
| // 제목은 변수 치환 미지원 — 변수는 공란으로 표기 | |
| const alternativeTitlePreview = document.querySelector('.alternative-title-preview'); | |
| if (alternativeTitlePreview) { | |
| alternativeTitlePreview.textContent = alternativeTitlePreview.textContent.replace(/[#$]?\{[^}]*\}/g, ''); | |
| } | |
| }) | |
| </script> | |
변경 전layer_preview_mobile_send_sms.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev sms-contents-preview" style="white-space: pre-wrap;"><?= $mainContents ?></div> | |
| </section> | |
| <script> | |
| const smsPreview = document.querySelector('.sms-contents-preview'); | |
| $(document).ready(() => { | |
| smsPreview.textContent = resolveReplaceCodeForPreview(smsPreview.textContent); | |
| }) | |
| </script> | |
변경 후layer_preview_mobile_send_sms.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <?php /* pre-wrap 은 본문에만 — 말풍선에 걸면 템플릿 마크업의 공백·줄바꿈까지 렌더링됨 */ ?> | |
| <div class="ncua-prev"> | |
| <?php if (($mainTitle ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview sms-title-preview"><?= gd_htmlspecialchars($mainTitle) ?></div> | |
| <?php endif; ?> | |
| <div class="sms-contents-preview" style="white-space: pre-wrap;"><?= $mainContents ?></div> | |
| </div> | |
| </section> | |
| <script> | |
| const smsPreview = document.querySelector('.sms-contents-preview'); | |
| $(document).ready(() => { | |
| smsPreview.textContent = resolveReplaceCodeForPreview(smsPreview.textContent); | |
| // 제목은 변수 치환 미지원 — 변수는 공란으로 표기 | |
| const smsTitlePreview = document.querySelector('.sms-title-preview'); | |
| if (smsTitlePreview) { | |
| smsTitlePreview.textContent = smsTitlePreview.textContent.replace(/[#$]?\{[^}]*\}/g, ''); | |
| } | |
| }) | |
| </script> | |
변경 전sms_auto.php
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientMode]" value="<?php echo $typeData['recipientMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientSno]" value="<?php echo $typeData['recipientSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientContents]" rows="4" class="form-control"><?php echo $typeData['recipientContents']; ?></textarea> | |
| </td> | |
| <?php } ?> | |
| <td class="form-inline"> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberMode]" value="<?php echo $typeData['memberMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberSno]" value="<?php echo $typeData['memberSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberContents]" rows="4" class="form-control"><?php echo $typeData['memberContents']; ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-blue">운영자 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminMode]" value="<?php echo $typeData['adminMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminSno]" value="<?php echo $typeData['adminSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminContents]" rows="4" | |
| class="form-control <?php if ($sKey == 'admin') { ?> width100p <?php } ?>"><?php echo $typeData['adminContents']; ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-orange-red">회원 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" rows="4" class="form-control"><?php echo $typeData['providerContents']; ?></textarea> | |
| <?php } else { ?> | |
| <?php if ($sKey == 'admin') { ?> | |
| <div class="text-center text-orange-red">본사 전용</div> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" value="<?php echo $typeData['providerContents']; ?>"/> | |
| <?php } ?> | |
| </tr> | |
| <?php | |
| <script type="text/javascript"> | |
| <!-- | |
| $(document).ready(function () { | |
| $('.btn-change-password').click(function () { | |
| $.get('../share/layer_sms_password.php?mode=change', function () { | |
| BootstrapDialog.closeAll(); | |
변경 후sms_auto.php
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientMode]" value="<?php echo $typeData['recipientMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientSno]" value="<?php echo $typeData['recipientSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][recipientMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['recipientMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][recipientContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['recipientContents'] ?></textarea> | |
| </td> | |
| <?php } ?> | |
| <td class="form-inline"> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberMode]" value="<?php echo $typeData['memberMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberSno]" value="<?php echo $typeData['memberSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][memberMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['memberMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][memberContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['memberContents'] ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-blue">운영자 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminMode]" value="<?php echo $typeData['adminMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminSno]" value="<?php echo $typeData['adminSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][adminMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['adminMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminContents]" rows="4" | |
| class="form-control js-sms-auto-contents <?php if ($sKey == 'admin') { ?> width100p <?php } ?>"><?= $typeData['adminContents'] ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-orange-red">회원 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['providerMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['providerContents'] ?></textarea> | |
| <?php } else { ?> | |
| <?php if ($sKey == 'admin') { ?> | |
| <div class="text-center text-orange-red">본사 전용</div> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" value="<?php echo $typeData['providerContents']; ?>"/> | |
| <input type="hidden" name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerMessageTitle]" value="<?= gd_isset($typeData['providerMessageTitle']) ?>"/> | |
| <?php } ?> | |
| </tr> | |
| <?php | |
| <script type="text/javascript"> | |
| <!-- | |
| $(document).ready(function () { | |
| // 제목 바이트 계산 (한글 등 멀티바이트 2byte, ASCII 1byte, 개행 제외) | |
| function smsAutoStringToByte(str) { | |
| var length = 0; | |
| for (var i = 0; i < str.length; i++) { | |
| if (escape(str.charAt(i)).length >= 4) length += 2; | |
| else if (escape(str.charAt(i)) != "%0D") length++; | |
| } | |
| return length; | |
| } | |
| // 이모티콘 제거 (서로게이트 페어 + 변형선택자, 기획: 제목·본문 입력 불가) | |
| function smsAutoStripEmoji(str) { | |
| if (!str) return str; | |
| return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '').replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| // 자동발송 제목 영역은 항상 활성 노출(C3). 본문은 이모티콘만 자동 제거. | |
| $('.js-sms-auto-contents').on('keyup change', function () { | |
| var $ta = $(this); | |
| var stripped = smsAutoStripEmoji($ta.val()); | |
| if (stripped !== $ta.val()) { $ta.val(stripped); } | |
| }); | |
| $('.js-sms-auto-subject').on('keyup keydown', function () { | |
| var input = $(this); | |
| var text = smsAutoStripEmoji(input.val()); | |
| while (smsAutoStringToByte(text) > <?= $lmsSubjectLimit; ?>) { text = text.substring(0, text.length - 1); } | |
| input.val(text); | |
| }); | |
| $('.btn-change-password').click(function () { | |
| $.get('../share/layer_sms_password.php?mode=change', function () { | |
| BootstrapDialog.closeAll(); | |
변경 전sms_log.php
| $listHtml[] = '<td class="text-center number">' . ($data['receiverCnt'] * $lmsPoint) . '</td>'; | |
| } | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| $listHtml[] = '<div class="div-contents">' . $data['contents'] . '</div>'; | |
| if ($data['sendStatus'] === 'r' && $data['smsType'] === 'user') { | |
| $listHtml[] = '<div><button type="button" class="btn btn-xs btn-gray btn-modify">수정하기</button></div>'; | |
변경 후sms_log.php
| $listHtml[] = '<td class="text-center number">' . ($data['receiverCnt'] * $lmsPoint) . '</td>'; | |
| } | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] === 'lms') { | |
| $subjectText = ($data['subject'] !== null && $data['subject'] !== '') ? $data['subject'] : '[' . __('제목없음') . ']'; | |
| $listHtml[] = '<div class="div-subject text-darkblue"><strong>' . gd_htmlspecialchars($subjectText) . '</strong></div>'; | |
| } | |
| $listHtml[] = '<div class="div-contents">' . $data['contents'] . '</div>'; | |
| if ($data['sendStatus'] === 'r' && $data['smsType'] === 'user') { | |
| $listHtml[] = '<div><button type="button" class="btn btn-xs btn-gray btn-modify">수정하기</button></div>'; | |
변경 전sms_send.php
| return length; | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var contentsText = textarea.val(); | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| setContentsLength('smsContents', 'smsStringCount'); | |
| } | |
| function setReceiverCount() { | |
| var checkedType = $('[name=receiverType]:checked').val(); | |
| var receiverCount = 0, agreeCount = 0, rejectCount = 0; | |
| dialog: false, | |
| debug: true, | |
| submitHandler: function (form) { | |
| console.log('submitHan', form); | |
| var divisionInt = 1; | |
| if ($('input[name=sendFl]').val() === 'lms') { | |
| divisionInt = <?php echo $lmsPoint;?>; | |
| <div class="notice-danger pull-left mgl15 display-none">회원 외 치환코드는 정상 적용되지 않으니 저장된 메시지 수정 시에만 이용바랍니다.</div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| <div class="col-xs-12"> | |
| <div class="notice-info">URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a></div> | |
| <div class="notice-info">치환코드 사용 시 LMS로 발송될 수 있으며 일부 문자가 포인트 부족으로 발송되지 않을 수 있습니다.<br/>- 포인트 충전 후 <a href="../member/sms_log.php" class="btn-link" target="_blank">SMS 발송 내역 보기</a>에서 재발송하실 수 있습니다.</div> | |
| <div class="notice-danger sms-large-caution">발송내용에 이모지 또는 사용 불가능한 특수문자, 맞춤법이 바르지 않은 문자가 포함되어있으면 일부 내용은 삭제되고 발송되오니 주의하시기 바랍니다.<br/>대량 SMS(LMS) 발송 시 이모지를 사용하지 않는 것과 맞춤법에 어긋나는 문자가 입력 되지는 않았는지 확인하시는 것을 권장 드리며,<br/> 발송 내용에 사용가능한 특수문자는 매뉴얼을 참고하시기 바랍니다.</div> | |
| </div> | |
| </div> | |
| <%= checkbox %> <%= subject %> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-save" data-text="저장">수정</button> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-insert mgr5">삽입</button> | |
| <label class="width100p pdt5"> | |
| <textarea rows="13" class="form-control width100p" name="contents"><%= contents %></textarea> | |
| </label> | |
변경 후sms_send.php
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var stripped = stripEmoji(textarea.val()); | |
| if (stripped !== textarea.val()) { | |
| textarea.val(stripped); | |
| } | |
| var contentsText = stripped; | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| $('#smsSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#smsSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미발송) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| setContentsLength('smsContents', 'smsStringCount'); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#smsSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| var adChecked = $('input[name=sms080Reject]').is(':checked'); | |
| var byte = stringToByte(text); | |
| if (adChecked && byte > limit) { | |
| // C4-2: (광고) 자동 삽입으로 40Byte 초과 -> 절삭하지 않고 에러 표기 | |
| input.val(text); | |
| setSubjectOver(true); | |
| } else { | |
| // C1-1: 직접 입력 40Byte 초과분 자동삭제 | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| byte = stringToByte(text); | |
| setSubjectOver(false); | |
| } | |
| $('#smsSubjectCount').val(byte); | |
| } | |
| function setSubjectOver(isOver) { | |
| var input = $('#smsSubject'); | |
| if (isOver) { | |
| input.addClass('js-subject-over').css('border-color', '#e74c3c'); | |
| $('#smsSubjectCount').css('color', '#e74c3c'); | |
| } else { | |
| input.removeClass('js-subject-over').css('border-color', ''); | |
| $('#smsSubjectCount').css('color', ''); | |
| } | |
| } | |
| function setReceiverCount() { | |
| var checkedType = $('[name=receiverType]:checked').val(); | |
| var receiverCount = 0, agreeCount = 0, rejectCount = 0; | |
| dialog: false, | |
| debug: true, | |
| submitHandler: function (form) { | |
| // C4-2: 제목 40Byte 초과(광고 삽입 등) 시 발송 차단 | |
| if ($('input[name=sendFl]').val() === 'lms' && $('#smsSubject').length && stringToByte(stripEmoji($('#smsSubject').val())) > <?= $lmsSubjectLimit; ?>) { | |
| BootstrapDialog.show({title: '경고', message: '제목은 최대 <?= $lmsSubjectLimit; ?>bytes까지 입력 가능합니다.', closable: true}); | |
| $('#smsSubject').focus(); | |
| return false; | |
| } | |
| var divisionInt = 1; | |
| if ($('input[name=sendFl]').val() === 'lms') { | |
| divisionInt = <?php echo $lmsPoint;?>; | |
| <div class="notice-danger pull-left mgl15 display-none">회원 외 치환코드는 정상 적용되지 않으니 저장된 메시지 수정 시에만 이용바랍니다.</div> | |
| </div> | |
| </div> | |
| <div class="row pdt5 js-subject-row"> | |
| <div class="col-xs-3 pdr0"> | |
| <input type="text" name="smsSubject" id="smsSubject" class="form-control width100p" placeholder="제목을 입력해주세요." value="<?= gd_isset($smsSubject); ?>" onkeyup="setSubjectLength();" onkeydown="setSubjectLength();" disabled="disabled"/> | |
| <div class="mgt5"> | |
| <input type="text" id="smsSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| <div class="col-xs-12"> | |
| <div class="notice-info">URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a></div> | |
| <div class="notice-info">치환코드 사용 시 LMS로 발송될 수 있으며 일부 문자가 포인트 부족으로 발송되지 않을 수 있습니다.<br/>- 포인트 충전 후 <a href="../member/sms_log.php" class="btn-link" target="_blank">SMS 발송 내역 보기</a>에서 재발송하실 수 있습니다.</div> | |
| <div class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</div> | |
| <div class="notice-danger sms-large-caution">발송내용에 이모지 또는 사용 불가능한 특수문자, 맞춤법이 바르지 않은 문자가 포함되어있으면 일부 내용은 삭제되고 발송되오니 주의하시기 바랍니다.<br/>대량 SMS(LMS) 발송 시 이모지를 사용하지 않는 것과 맞춤법에 어긋나는 문자가 입력 되지는 않았는지 확인하시는 것을 권장 드리며,<br/> 발송 내용에 사용가능한 특수문자는 매뉴얼을 참고하시기 바랍니다.</div> | |
| </div> | |
| </div> | |
| <%= checkbox %> <%= subject %> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-save" data-text="저장">수정</button> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-insert mgr5">삽입</button> | |
| <input type="text" name="messageTitle" class="form-control width100p mgt5 js-sms-contents-subject" placeholder="제목을 입력해주세요." value="<%= messageTitle %>" disabled="disabled"/> | |
| <label class="width100p pdt5"> | |
| <textarea rows="13" class="form-control width100p" name="contents"><%= contents %></textarea> | |
| </label> | |
변경 전cart_remind_regist.php
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| } | |
| changeCartRemindContentsLength(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $subject.length && !$subject.prop('disabled')) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| changeCartRemindSubjectLength(); | |
| }); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl js-sms080-update"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| displayCartRemindCouponLink(); | |
| changeCartRemindType(); | |
| changeCartRemindSendType(); | |
| changeCartRemindManualDirectPeriod(); | |
| changeCartRemindContentsLength(); | |
| // 광고성 문구 추가 | |
| $('input[name="sms080Reject"]').click(function (e) { | |
| $('.js-sms080-update').val($('.js-sms080-update').val().replace(/(\n무료거부\s[0-9\-]*)/g, '')); | |
| if(e.target.checked){ | |
| $('.js-sms080-update').val($('.js-sms080-update').val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| }; | |
| }); | |
| }); | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var contentsText = $('textarea[name=cartRemindSendMessage]').val(); | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| } | |
| $('#cartRemindSendMessageCount').val(textLength); | |
| } | |
| // 발송유형 따른 폼 변경 | |
| function changeCartRemindType() { | |
| if ($('input:radio[name="cartRemindType"]:checked').val() == 'manual') { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| } | |
| } | |
| // 발급방식에 따른 폼 변경 | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후cart_remind_regist.php
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| } | |
| changeCartRemindContentsLength(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $subject.length && !$subject.prop('disabled')) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| changeCartRemindSubjectLength(); | |
| }); | |
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10 js-cart-subject-row"> | |
| <input type="text" name="cartRemindSendSubject" id="cartRemindSendSubject" class="form-control width-xl" placeholder="제목을 입력해주세요." value="<?= gd_isset($cartRemindData['cartRemindSendSubject']); ?>" disabled="disabled"/> | |
| <input type="text" id="cartRemindSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl js-sms080-update"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| <p class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| $('#cartRemindSendSubject').on('keyup keydown', changeCartRemindSubjectLength); | |
| displayCartRemindCouponLink(); | |
| changeCartRemindType(); | |
| changeCartRemindSendType(); | |
| changeCartRemindManualDirectPeriod(); | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| // 광고성 문구 추가 (본문: (광고) 접두 + 무료거부 접미 / LMS 제목: (광고) 접두) | |
| $('input[name="sms080Reject"]').click(function (e) { | |
| var $body = $('.js-sms080-update'); | |
| $body.val($body.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| var $subject = $('#cartRemindSendSubject'); | |
| if ($subject.length) { | |
| $subject.val($subject.val().replace(/^\(광고\)/, '')); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| }); | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var $cartTa = $('textarea[name=cartRemindSendMessage]'); | |
| var strippedBody = stripEmoji($cartTa.val()); | |
| if (strippedBody !== $cartTa.val()) { | |
| $cartTa.val(strippedBody); | |
| } | |
| var contentsText = strippedBody; | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| } | |
| $('#cartRemindSendMessageCount').val(textLength); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function changeCartRemindSubjectLength() { | |
| var input = $('#cartRemindSendSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#cartRemindSubjectCount').val(stringToByte(text)); | |
| } | |
| // 발송유형 따른 폼 변경 | |
| function changeCartRemindType() { | |
| if ($('input:radio[name="cartRemindType"]:checked').val() == 'manual') { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미저장/미발송) | |
| } | |
| } | |
| // 발급방식에 따른 폼 변경 | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| </script> | |
변경 전comeback_coupon_regist.php
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $smsSubject.length && !$smsSubject.prop('disabled')) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| }); | |
| } | |
| </script> | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
| } | |
| </script> | |
| <button type="button" class="btn btn-white btn-sm pull-right js-toggle-replace-code" data-target=".replace_code_area" data-text="치환코드 닫기">치환코드 보기</button> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| 링크는 단축 URL로 자동 변환하였습니다.<br/> | |
| [단축 URL] 앱을 이용하여 단축 URL을 생성하면, 조회수 및 통계 자료를 확인하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a> | |
| </div> | |
| </div> | |
| </div> | |
| </td> | |
| return length; | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var contentsText = textarea.val(); | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| // 글자수 체크 | |
| $('textarea[name=smsContents]').keyup(setSendLength).change(setSendLength); | |
| $("#frmCoupon").validate({ | |
| submitHandler: function (form) { | |
| changeTargetType(); | |
| checkSms(); | |
| setSendLength(); | |
| set_click_replace_code_insert('.replace-code-area .js-btn-insert'); | |
| set_change_focus_contents('textarea[name="smsContents"]'); | |
| set_click_sms080_contents(':checkbox[name="sms080Reject"]'); | |
| function set_click_sms080_contents (selector) { | |
| $(selector).click(function (e) { | |
| $send_contents.val($send_contents.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| }); | |
변경 후comeback_coupon_regist.php
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
| } | |
| </script> | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $smsSubject.length && !$smsSubject.prop('disabled')) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| }); | |
| } | |
| </script> | |
| <button type="button" class="btn btn-white btn-sm pull-right js-toggle-replace-code" data-target=".replace_code_area" data-text="치환코드 닫기">치환코드 보기</button> | |
| </div> | |
| </div> | |
| <div class="row pdt5 js-subject-row"> | |
| <div class="col-xs-3 pdr0"> | |
| <input type="text" name="smsSubject" id="smsSubject" class="form-control width100p" placeholder="제목을 입력해주세요." value="<?= gd_isset($couponData['smsSubject']) ?>" disabled="disabled"/> | |
| <div class="mgt5"> | |
| <input type="text" id="smsSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| 링크는 단축 URL로 자동 변환하였습니다.<br/> | |
| [단축 URL] 앱을 이용하여 단축 URL을 생성하면, 조회수 및 통계 자료를 확인하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a> | |
| </div> | |
| <div class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</div> | |
| </div> | |
| </div> | |
| </td> | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#smsSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#smsSubjectCount').val(stringToByte(text)); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var stripped = stripEmoji(textarea.val()); | |
| if (stripped !== textarea.val()) { | |
| textarea.val(stripped); | |
| } | |
| var contentsText = stripped; | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| <?php if ($checkMode == 'canModify') { ?> | |
| $('#smsSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| <?php } ?> | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#smsSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| // 글자수 체크 | |
| $('textarea[name=smsContents]').keyup(setSendLength).change(setSendLength); | |
| $('#smsSubject').on('keyup keydown', setSubjectLength); | |
| $("#frmCoupon").validate({ | |
| submitHandler: function (form) { | |
| changeTargetType(); | |
| checkSms(); | |
| setSendLength(); | |
| setSubjectLength(); | |
| set_click_replace_code_insert('.replace-code-area .js-btn-insert'); | |
| set_change_focus_contents('textarea[name="smsContents"]'); | |
| set_click_sms080_contents(':checkbox[name="sms080Reject"]'); | |
| function set_click_sms080_contents (selector) { | |
| $(selector).click(function (e) { | |
| $send_contents.val($send_contents.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| var $smsSubject = $('#smsSubject'); | |
| if ($smsSubject.length) { | |
| $smsSubject.val($smsSubject.val().replace(/^\(광고\)/, '')); | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
변경 전layer_cart_remind_message.php
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| changeCartRemindSendType(); | |
| changeCartRemindContentsLength(); | |
| }); | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var contentsText = $('textarea[name=cartRemindSendMessage]').val(); | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| } | |
| } | |
| /** | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후layer_cart_remind_message.php
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10 js-cart-subject-row"> | |
| <input type="text" name="cartRemindSendSubject" id="cartRemindSendSubject" class="form-control width-xl" placeholder="제목을 입력해주세요." value="<?= gd_isset($cartRemindData['cartRemindSendSubject']); ?>" disabled="disabled"/> | |
| <input type="text" id="cartRemindSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| <p class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| $('#cartRemindSendSubject').on('keyup keydown', changeCartRemindSubjectLength); | |
| changeCartRemindSendType(); | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function changeCartRemindSubjectLength() { | |
| var input = $('#cartRemindSendSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#cartRemindSubjectCount').val(stringToByte(text)); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var $cartTa = $('textarea[name=cartRemindSendMessage]'); | |
| var strippedBody = stripEmoji($cartTa.val()); | |
| if (strippedBody !== $cartTa.val()) { | |
| $cartTa.val(strippedBody); | |
| } | |
| var contentsText = strippedBody; | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미저장/미발송) | |
| } | |
| } | |
| /** | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| </script> | |
변경 전layer_comeback_coupon_sms.php
| <col style="width:80%" /> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>발송 내용</th> | |
| <td> | |
변경 후layer_comeback_coupon_sms.php
| <col style="width:80%" /> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>제목</th> | |
| <td> | |
| <input type="text" class="form-control width100p" readonly="readonly" value="<?= gd_isset($data['smsSubject']) !== '' ? gd_isset($data['smsSubject']) : '[제목없음]' ?>"/> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>발송 내용</th> | |
| <td> | |
변경 전layer_standby_sms.php
| */ | |
| ?> | |
| <form action="" method="post"> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-left"> | |
| <span class="sms-type text-darkblue">SMS : 발송 건당 1포인트 차감</span> | |
| <span class="lms-type text-orange-red display-none">LMS : 발송 건당 <?php echo $lmsPoint; ?>포인트 차감</span> | |
| </div> | |
| <div class="pull-right"> | |
| <input type="text" id="smsStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / | |
| <span class="sms-type"><?php echo $smsStringLimit; ?></span><span class="lms-type display-none"><?php echo number_format($lmsStringLimit); ?></span> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <textarea name="contents" id="contents" rows="8" class="form-control"><?= $data['contents']; ?></textarea> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="center modal-footer"> | |
| <button type="submit" id="modify" class="btn btn-red">수정</button> | |
| $(document).ready(function () { | |
| var $textarea = $('textarea[name=contents]'); | |
| $textarea.on('keyup change', setSendLength).trigger('change'); | |
| }); | |
| function setSendLength() { | |
| setContentsLength('contents', 'smsStringCount'); | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후layer_standby_sms.php
| */ | |
| ?> | |
| <form action="" method="post"> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-right form-inline"> | |
| <input type="text" id="subjectStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div style="overflow:hidden; padding-right:10px;"> | |
| <input type="text" name="subject" id="subject" class="form-control" placeholder="제목을 입력해주세요." value="<?= gd_isset($data['subject']); ?>" disabled="disabled"/> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row mgt10"> | |
| <div class="col-xs-12"> | |
| <textarea name="contents" id="contents" rows="8" class="form-control"><?= $data['contents']; ?></textarea> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-left"> | |
| <span class="sms-type text-darkblue">SMS : 발송 건당 1포인트 차감</span> | |
| <span class="lms-type text-orange-red display-none">LMS : 발송 건당 <?php echo $lmsPoint; ?>포인트 차감</span> | |
| </div> | |
| <div class="pull-right"> | |
| <input type="text" id="smsStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / | |
| <span class="sms-type"><?php echo $smsStringLimit; ?></span><span class="lms-type display-none"><?php echo number_format($lmsStringLimit); ?></span> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="center modal-footer"> | |
| <button type="submit" id="modify" class="btn btn-red">수정</button> | |
| $(document).ready(function () { | |
| var $textarea = $('textarea[name=contents]'); | |
| $textarea.on('keyup change', setSendLength).trigger('change'); | |
| $('#subject').on('keyup keydown', setSubjectLength); | |
| setSubjectLength(); | |
| }); | |
| function setSendLength() { | |
| setContentsLength('contents', 'smsStringCount'); | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| $('#subject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#subject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미발송) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#subject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#subjectStringCount').val(stringToByte(text)); | |
| } | |
| </script> | |
변경 전member_crm_sms.php
| $listHtml[] = '<td class="text-center">' . $sSendFl . '</td>'; | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] != 'kakao') { | |
| $listHtml[] = '<div>' . $data['contents'] . '</div>'; | |
| } else { | |
| $listHtml[] = '<div>' . nl2br($data['templateContent']) . '</div>'; | |
변경 후member_crm_sms.php
| $listHtml[] = '<td class="text-center">' . $sSendFl . '</td>'; | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] != 'kakao') { | |
| // LMS 제목 — 있으면 그대로, 없으면 '[제목없음]' 표시(표시 시점 변환). 제목은 LMS 한정. | |
| if ($data['sendFl'] == 'lms') { | |
| $smsSubject = trim($data['subject'] ?? ''); | |
| if ($smsSubject === '') { | |
| $smsSubject = '[제목없음]'; | |
| } | |
| $listHtml[] = '<div><strong>' . gd_htmlspecialchars($smsSubject) . '</strong></div>'; | |
| } | |
| $listHtml[] = '<div>' . $data['contents'] . '</div>'; | |
| } else { | |
| $listHtml[] = '<div>' . nl2br($data['templateContent']) . '</div>'; | |
변경 전CartRemind.php
| $getCartRemindSend['autoSendTime'] = $cartRemindData['cartRemindAutoSendTime']; | |
| $getCartRemindSend['smsType'] = $cartRemindData['cartRemindSendType']; | |
| $getCartRemindSend['message'] = $cartRemindData['cartRemindSendMessage']; | |
| $getCartRemindSend['cartUrl'] = $cartRemindData['cartRemindSendUrl']; | |
| if ($cartRemindData['cartRemindCoupon'] > 0) { | |
| $getCartRemindSend['coupon'] = $cartRemindData['cartRemindCoupon']; | |
| $validator->add('cartRemindCoupon', null, null); // 발송쿠폰 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| switch (substr($arrData['mode'], 0, 6)) { | |
| case 'insert' : { | |
| // 저장 | |
| $validator->add('cartRemindNo', 'number', true); // 장바구니 알림 고유번호 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // 수정 | |
| $arrBind = $this->db->get_binding(DBTableField::tableCartRemind(), $arrData, 'update', gd_array_keys($arrData), ['cartRemindNo']); | |
| $this->db->bind_param_push($arrBind['bind'], 'i', $arrData['cartRemindNo']); | |
| } | |
| // sms, lms | |
| $smsSendData['sendFl'] = $cartRemindSendData['smsType']; | |
| // ?? | |
| $smsSendData['agreeCnt'] = ''; | |
변경 후CartRemind.php
| $getCartRemindSend['autoSendTime'] = $cartRemindData['cartRemindAutoSendTime']; | |
| $getCartRemindSend['smsType'] = $cartRemindData['cartRemindSendType']; | |
| $getCartRemindSend['message'] = $cartRemindData['cartRemindSendMessage']; | |
| $getCartRemindSend['subject'] = $cartRemindData['cartRemindSendSubject'] ?? ''; | |
| $getCartRemindSend['cartUrl'] = $cartRemindData['cartRemindSendUrl']; | |
| if ($cartRemindData['cartRemindCoupon'] > 0) { | |
| $getCartRemindSend['coupon'] = $cartRemindData['cartRemindCoupon']; | |
| $validator->add('cartRemindCoupon', null, null); // 발송쿠폰 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| $validator->add('cartRemindSendSubject', null, null); // LMS 제목 (선택, lms 시) | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // LMS 제목은 LMS 상태에서만 저장(C5). 본문이 SMS면 제목 영역은 저장하지 않음(빈값). | |
| if (gd_isset($arrData['cartRemindSendType']) === 'sms') { | |
| $arrData['cartRemindSendSubject'] = ''; | |
| } | |
| switch (substr($arrData['mode'], 0, 6)) { | |
| case 'insert' : { | |
| // 저장 | |
| $validator->add('cartRemindNo', 'number', true); // 장바구니 알림 고유번호 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| $validator->add('cartRemindSendSubject', null, null); // LMS 제목 (선택, lms 시) | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // LMS 제목은 LMS 상태에서만 저장(C5). 본문이 SMS면 제목 영역은 저장하지 않음(빈값). | |
| if (gd_isset($arrData['cartRemindSendType']) === 'sms') { | |
| $arrData['cartRemindSendSubject'] = ''; | |
| } | |
| // 수정 | |
| $arrBind = $this->db->get_binding(DBTableField::tableCartRemind(), $arrData, 'update', gd_array_keys($arrData), ['cartRemindNo']); | |
| $this->db->bind_param_push($arrBind['bind'], 'i', $arrData['cartRemindNo']); | |
| } | |
| // sms, lms | |
| $smsSendData['sendFl'] = $cartRemindSendData['smsType']; | |
| // LMS 제목 (LMS 발송 시에만 SmsAdmin 에서 사용) | |
| $smsSendData['smsSubject'] = $cartRemindSendData['subject'] ?? ''; | |
| // ?? | |
| $smsSendData['agreeCnt'] = ''; | |
변경 전CouponAdmin.php
| 지금 바로 확인하세요!"; | |
| } | |
| $validator->add('smsContents', 'required', true); // SMS 발송 내용 | |
| // 전송일 null처리 | |
| $arrData['sendDt'] = null; | |
| $smsSendData['smsPoint'] = Sms::getPoint(); | |
| // 전송 내용 | |
| $smsSendData['smsContents'] = str_replace('rc_memNm', 'memNm', $getData['smsContents']); | |
| // 치환 코드 그룹 | |
| $smsSendData['replaceCodeGroup'] = 'promotion'; | |
| // 전송요청 수 | |
변경 후CouponAdmin.php
| 지금 바로 확인하세요!"; | |
| } | |
| $validator->add('smsContents', 'required', true); // SMS 발송 내용 | |
| $validator->add('smsSubject', null, null); // LMS 제목 (검증 없음, garbageDelete 방지용 등록) | |
| // 전송일 null처리 | |
| $arrData['sendDt'] = null; | |
| $smsSendData['smsPoint'] = Sms::getPoint(); | |
| // 전송 내용 | |
| $smsSendData['smsContents'] = str_replace('rc_memNm', 'memNm', $getData['smsContents']); | |
| // LMS 제목 (LMS 발송 시에만 SmsAdmin 에서 사용) | |
| $smsSendData['smsSubject'] = isset($getData['smsSubject']) ? $getData['smsSubject'] : ''; | |
| // 치환 코드 그룹 | |
| $smsSendData['replaceCodeGroup'] = 'promotion'; | |
| // 전송요청 수 | |
변경 전DBTableField.php
| ['val' => 'cartRemindAutoSendTime', 'typ' => 'i', 'def' => '10'], // 장바구니 알림 자동발송 시 발송 시간 | |
| ['val' => 'cartRemindSendType', 'typ' => 's', 'def' => 'lms'], // 장바구니 알림 전송 형식 - sms, lms | |
| ['val' => 'cartRemindSendMessage', 'typ' => 's', 'def' => '(광고)[{rc_mallNm}] {rc_memNm}님의 장바구니에 상품이 담겨 있습니다. 아래 장바구니 바로가기를 통해 바로 확인하실 수 있습니다. ▶ 장바구니 바로가기: {rc_cartRemindLink}'], // 장바구니 알림 전송 내용 | |
| ['val' => 'cartRemindSendUrl', 'typ' => 's', 'def' => ''], // 장바구니 알림 바로가기 링크 | |
| ['val' => 'cartRemindInsertAdminId', 'typ' => 's', 'def' => null], // 장바구니 알림 등록자 아이디 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => 0], // 장바구니 알림 등록자 키 | |
| ['val' => 'smsAutoType', 'typ' => 's', 'def' => null], // SMS 자동발송 수신 종류 (member, admin, provider) | |
| ['val' => 'subject', 'typ' => 's', 'def' => null], // SMS 템플릿 제목 | |
| ['val' => 'contents', 'typ' => 's', 'def' => null], // SMS 템플릿 내용 | |
| ['val' => 'description', 'typ' => 's', 'def' => null], // 설명 | |
| ['val' => 'isUserBasic', 'typ' => 's', 'def' => 'n'], // 전송타입(user)기본제공여부 | |
| ['val' => 'modDt', 'typ' => 's', 'def' => null], // 수정일 | |
| ['val' => 'smsFl', 'typ' => 's', 'def' => 'n'], // sms동시 발송여부 - y:발송 / n:미발송 | |
| ['val' => 'smsSpamFl', 'typ' => 's', 'def' => 'n'], // 광고성 문구 추가 - y:추가 / n:미추가 | |
| ['val' => 'smsContents', 'typ' => 's', 'def' => ''], // SMS 발송 내용 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => ''], // 등록 관리자 고유번호 | |
| ['val' => 'deleteFl', 'typ' => 's', 'def' => 'n'], // 삭제 flag - y:삭제 / n:미삭제 | |
| ['val' => 'sendDt', 'typ' => 's', 'def' => null], // 전송일 | |
변경 후DBTableField.php
| ['val' => 'cartRemindAutoSendTime', 'typ' => 'i', 'def' => '10'], // 장바구니 알림 자동발송 시 발송 시간 | |
| ['val' => 'cartRemindSendType', 'typ' => 's', 'def' => 'lms'], // 장바구니 알림 전송 형식 - sms, lms | |
| ['val' => 'cartRemindSendMessage', 'typ' => 's', 'def' => '(광고)[{rc_mallNm}] {rc_memNm}님의 장바구니에 상품이 담겨 있습니다. 아래 장바구니 바로가기를 통해 바로 확인하실 수 있습니다. ▶ 장바구니 바로가기: {rc_cartRemindLink}'], // 장바구니 알림 전송 내용 | |
| ['val' => 'cartRemindSendSubject', 'typ' => 's', 'def' => ''], // 장바구니 알림 LMS 제목 | |
| ['val' => 'cartRemindSendUrl', 'typ' => 's', 'def' => ''], // 장바구니 알림 바로가기 링크 | |
| ['val' => 'cartRemindInsertAdminId', 'typ' => 's', 'def' => null], // 장바구니 알림 등록자 아이디 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => 0], // 장바구니 알림 등록자 키 | |
| ['val' => 'smsAutoType', 'typ' => 's', 'def' => null], // SMS 자동발송 수신 종류 (member, admin, provider) | |
| ['val' => 'subject', 'typ' => 's', 'def' => null], // SMS 템플릿 제목 | |
| ['val' => 'contents', 'typ' => 's', 'def' => null], // SMS 템플릿 내용 | |
| ['val' => 'messageTitle', 'typ' => 's', 'def' => null], // LMS 메시지 제목 | |
| ['val' => 'description', 'typ' => 's', 'def' => null], // 설명 | |
| ['val' => 'isUserBasic', 'typ' => 's', 'def' => 'n'], // 전송타입(user)기본제공여부 | |
| ['val' => 'modDt', 'typ' => 's', 'def' => null], // 수정일 | |
| ['val' => 'smsFl', 'typ' => 's', 'def' => 'n'], // sms동시 발송여부 - y:발송 / n:미발송 | |
| ['val' => 'smsSpamFl', 'typ' => 's', 'def' => 'n'], // 광고성 문구 추가 - y:추가 / n:미추가 | |
| ['val' => 'smsContents', 'typ' => 's', 'def' => ''], // SMS 발송 내용 | |
| ['val' => 'smsSubject', 'typ' => 's', 'def' => ''], // LMS 제목 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => ''], // 등록 관리자 고유번호 | |
| ['val' => 'deleteFl', 'typ' => 's', 'def' => 'n'], // 삭제 flag - y:삭제 / n:미삭제 | |
| ['val' => 'sendDt', 'typ' => 's', 'def' => null], // 전송일 | |
변경 전SmsAdmin.php
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['sno'] = $autoData[$autoType . 'Sno']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['subject'] = $autoData['subject']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['contents'] = $autoData[$autoType . 'Contents']; | |
| // $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['smsType'] = $smsType; | |
| unset($request[$smsType][$autoCode][$autoType . 'Mode']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Sno']); | |
| unset($request[$smsType][$autoCode]['subject']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Contents']); | |
| } | |
| } | |
| } | |
| $getData = gd_htmlspecialchars_stripslashes($this->db->query_fetch($strSQL, null, false)); | |
| foreach ($getData as $data) { | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['contents'] = $data['contents']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['sno'] = $data['sno']; | |
| } | |
| unset($getData); | |
| foreach ($arrType as $sendType) { | |
| if (isset($setData[$keyType][$val['code']][$sendType]['contents']) === true) { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $setData[$keyType][$val['code']][$sendType]['contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'update'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = $setData[$keyType][$val['code']][$sendType]['sno']; | |
| } else { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $val[$sendType . 'Contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'insert'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = ''; | |
| } | |
| } | |
| if ($receiverData['sendFl'] === 'lms') { | |
| $message = new \Component\Sms\LmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } else { | |
| $message = new \Component\Sms\SmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } | |
변경 후SmsAdmin.php
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['sno'] = $autoData[$autoType . 'Sno']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['subject'] = $autoData['subject']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['contents'] = $autoData[$autoType . 'Contents']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['messageTitle'] = gd_isset($autoData[$autoType . 'MessageTitle'], ''); | |
| // $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['smsType'] = $smsType; | |
| unset($request[$smsType][$autoCode][$autoType . 'Mode']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Sno']); | |
| unset($request[$smsType][$autoCode]['subject']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Contents']); | |
| unset($request[$smsType][$autoCode][$autoType . 'MessageTitle']); | |
| } | |
| } | |
| } | |
| $getData = gd_htmlspecialchars_stripslashes($this->db->query_fetch($strSQL, null, false)); | |
| foreach ($getData as $data) { | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['contents'] = $data['contents']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['messageTitle'] = $data['messageTitle']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['sno'] = $data['sno']; | |
| } | |
| unset($getData); | |
| foreach ($arrType as $sendType) { | |
| if (isset($setData[$keyType][$val['code']][$sendType]['contents']) === true) { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $setData[$keyType][$val['code']][$sendType]['contents']; | |
| $messageTitle = gd_isset($setData[$keyType][$val['code']][$sendType]['messageTitle'], ''); | |
| $smsAutoType[$keyType][$key][$sendType . 'MessageTitle'] = $messageTitle; | |
| $smsAutoType[$keyType][$key][$sendType . 'Title'] = $messageTitle; // CRM 뷰 호환(messageTitle 일원화) | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'update'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = $setData[$keyType][$val['code']][$sendType]['sno']; | |
| } else { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $val[$sendType . 'Contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'MessageTitle'] = ''; | |
| $smsAutoType[$keyType][$key][$sendType . 'Title'] = ''; // CRM 뷰 호환 | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'insert'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = ''; | |
| } | |
| } | |
| if ($receiverData['sendFl'] === 'lms') { | |
| $message = new \Component\Sms\LmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| // LMS 제목 (미입력 시 빈 값) | |
| // 튜닝 상점 대비: 구버전 SmsSender(setSubject 미보유)에서 발송 중단 방지 | |
| if (method_exists($transport, 'setSubject')) { | |
| $transport->setSubject($receiverData['smsSubject'] ?? ''); | |
| } | |
| } else { | |
| $message = new \Component\Sms\SmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } | |
변경 전SmsAuto.php
| { | |
| $logger = $this->logger; | |
| $binds = []; | |
| $this->db->strField = 'smsType, smsAutoType, contents, subject'; | |
| $this->db->strJoin = DB_SMS_CONTENTS; | |
| $this->db->strWhere = 'smsType= ? AND smsAutoCode = ? AND smsAutoType IN (\'' . gd_implode('\', \'', $wheres) . '\') AND contents != \'\' AND contents IS NOT NULL'; | |
| $this->db->bind_param_push($binds, 's', $this->smsType); | |
| } | |
| $transport->setSmsPoint(Sms::getPoint()); | |
| $transport->setMessage($message); | |
| $transport->setSmsType($item['smsType']); | |
| $transport->setReceiver($receiverData); | |
| $transport->setSendDate($this->smsAutoSendDate); | |
변경 후SmsAuto.php
| { | |
| $logger = $this->logger; | |
| $binds = []; | |
| $this->db->strField = 'smsType, smsAutoType, contents, subject, messageTitle'; | |
| $this->db->strJoin = DB_SMS_CONTENTS; | |
| $this->db->strWhere = 'smsType= ? AND smsAutoCode = ? AND smsAutoType IN (\'' . gd_implode('\', \'', $wheres) . '\') AND contents != \'\' AND contents IS NOT NULL'; | |
| $this->db->bind_param_push($binds, 's', $this->smsType); | |
| } | |
| $transport->setSmsPoint(Sms::getPoint()); | |
| $transport->setMessage($message); | |
| // LMS 제목 (설정된 자동발송 문구 제목 - LMS 발송 시에만 SmsSender 에서 사용, 미입력 시 [제목없음]) | |
| // 튜닝 상점 대비: 구버전 SmsSender(setSubject 미보유)에서 발송 중단 방지 | |
| if (method_exists($transport, 'setSubject')) { | |
| $transport->setSubject($item['messageTitle'] ?? ''); | |
| } | |
| $transport->setSmsType($item['smsType']); | |
| $transport->setReceiver($receiverData); | |
| $transport->setSendDate($this->smsAutoSendDate); | |
변경 전SmsSender.php
| protected $isThrowPasswordException = false; | |
| /** @var string|null SMS 발송 트리거 타입 (예: FALLBACK) */ | |
| protected $sendTriggerType; | |
| /** @var string SMS 대량발송 파일 경로 */ | |
| private $_smsLargeFilePath; | |
| /** @var object SMS 대량발송 TXT 파일 생성 로거 */ | |
| ]; | |
| //@formatter:on | |
| if ($this->_isLms()) { | |
| $this->sendSms['subject'] = ''; | |
| } | |
| if ($this->sendTriggerType !== null) { | |
| $this->sendSms['sendTriggerType'] = $this->sendTriggerType; | |
| ]; | |
| if ($this->_isLms()) { | |
| $this->smsLog['sendFl'] = 'lms'; | |
| } | |
| } | |
| $this->sendTriggerType = $sendTriggerType; | |
| } | |
| /** | |
| * @param bool $isThrowPasswordException | |
| */ | |
변경 후SmsSender.php
| protected $isThrowPasswordException = false; | |
| /** @var string|null SMS 발송 트리거 타입 (예: FALLBACK) */ | |
| protected $sendTriggerType; | |
| /** @var string|null LMS 제목 */ | |
| protected $subject; | |
| /** @var string SMS 대량발송 파일 경로 */ | |
| private $_smsLargeFilePath; | |
| /** @var object SMS 대량발송 TXT 파일 생성 로거 */ | |
| ]; | |
| //@formatter:on | |
| if ($this->_isLms()) { | |
| $this->sendSms['subject'] = $this->resolveSubject(); | |
| } | |
| if ($this->sendTriggerType !== null) { | |
| $this->sendSms['sendTriggerType'] = $this->sendTriggerType; | |
| ]; | |
| if ($this->_isLms()) { | |
| $this->smsLog['sendFl'] = 'lms'; | |
| $this->smsLog['subject'] = trim(preg_replace('/#?\{[^}]*\}/u', '', (string) $this->subject)); // 저장은 치환자 제거한 원문(빈값 유지), [제목없음] 변환은 발송/표시 시점만 | |
| } | |
| } | |
| $this->sendTriggerType = $sendTriggerType; | |
| } | |
| /** | |
| * LMS 제목 설정 (LMS 발송 시에만 사용) | |
| * | |
| * @param string|null $subject | |
| */ | |
| public function setSubject(?string $subject): void | |
| { | |
| $this->subject = $subject; | |
| } | |
| /** | |
| * 실발송용 LMS 제목 계산 | |
| * - 제목 치환자({..}/#{..})는 미지원이므로 공란 처리 | |
| * - LMS 인데 제목이 없으면(또는 치환자만 있어 공란) '[제목없음]' 으로 발송 | |
| * | |
| * @return string | |
| */ | |
| protected function resolveSubject(): string | |
| { | |
| // 치환자 제거 (제목 영역은 치환자 미지원 → 실발송 시 공란 처리) | |
| $subject = trim(preg_replace('/#?\{[^}]*\}/u', '', (string) $this->subject)); | |
| if ($subject === '') { | |
| return '[제목없음]'; | |
| } | |
| return $subject; | |
| } | |
| /** | |
| * @param bool $isThrowPasswordException | |
| */ | |
변경 전LayerPreviewMobileSendController.php
| switch ($sendMethod) { | |
| case 'SMS': | |
| $smsData = $payload['smsLmsRequest'] ?? []; | |
| $this->setData('mainContents', $smsData['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_sms.php'; | |
| $this->setData('friendtalk', $friendTalkData); | |
| $this->setData('alternativeContents', $friendTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_friendtalk.php'; | |
| break; | |
| $this->setData('template', $previewMeta); | |
| $this->setData('hasAddChannelButton', $hasAddChannelButton); | |
| $this->setData('alternativeContents', $alimTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_alimtalk.php'; | |
| break; | |
| $this->setData('myappPayload', $myappPushData); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $this->setData('alternativeContents', $payload['myappRequest']['alternativeInfo']['content'] ?? ''); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_myapp_push.php'; | |
| break; | |
| } | |
변경 후LayerPreviewMobileSendController.php
| switch ($sendMethod) { | |
| case 'SMS': | |
| $smsData = $payload['smsLmsRequest'] ?? []; | |
| $this->setData('mainTitle', $smsData['title'] ?? ''); | |
| $this->setData('mainContents', $smsData['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_sms.php'; | |
| $this->setData('friendtalk', $friendTalkData); | |
| $this->setData('alternativeContents', $friendTalkData['alternativeInfo']['content'] ?? ''); | |
| // 대체 제목 미입력 시 메인 메시지 타이틀(친구톡 헤더)이 있으면 카피하여 표기 (미리보기 전용) | |
| $alternativeTitle = $friendTalkData['alternativeInfo']['title'] ?? ''; | |
| if ($alternativeTitle === '' || $alternativeTitle === null) { | |
| $alternativeTitle = $friendTalkData['header'] ?? ''; | |
| } | |
| $this->setData('alternativeTitle', $alternativeTitle); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_friendtalk.php'; | |
| break; | |
| $this->setData('template', $previewMeta); | |
| $this->setData('hasAddChannelButton', $hasAddChannelButton); | |
| $this->setData('alternativeContents', $alimTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('alternativeTitle', $alimTalkData['alternativeInfo']['title'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_alimtalk.php'; | |
| break; | |
| $this->setData('myappPayload', $myappPushData); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $this->setData('alternativeContents', $payload['myappRequest']['alternativeInfo']['content'] ?? ''); | |
| // 대체 제목 미입력 시 메인 메시지 타이틀(푸시 제목)이 있으면 카피하여 표기 (미리보기 전용) | |
| $alternativeTitle = $payload['myappRequest']['alternativeInfo']['title'] ?? ''; | |
| if ($alternativeTitle === '' || $alternativeTitle === null) { | |
| $alternativeTitle = $myappPushData['pushSubject'] ?? ''; | |
| } | |
| $this->setData('alternativeTitle', $alternativeTitle); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_myapp_push.php'; | |
| break; | |
| } | |
변경 전LayerKakaoFriendtalkContentSettingController.php
| $friendtalkRequest = $defaultCampaignRequest['kakaoFriendtalkRequest'] ?? []; | |
| $initialTextContent = $friendtalkRequest['text']['content'] ?? ''; | |
| $initialAlternativeMessage = $defaultCampaignRequest['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('campaignMessageTypes', CampaignMessageType::cases()); | |
| $this->setData('friendtalkRequest', $friendtalkRequest); | |
| $this->setData('initialTextContent', $initialTextContent); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerKakaoFriendtalkContentSettingController.php
| $friendtalkRequest = $defaultCampaignRequest['kakaoFriendtalkRequest'] ?? []; | |
| $initialTextContent = $friendtalkRequest['text']['content'] ?? ''; | |
| $initialAlternativeMessage = $defaultCampaignRequest['smsLmsRequest']['content'] ?? ''; | |
| $initialAlternativeTitle = $defaultCampaignRequest['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('campaignMessageTypes', CampaignMessageType::cases()); | |
| $this->setData('friendtalkRequest', $friendtalkRequest); | |
| $this->setData('initialTextContent', $initialTextContent); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->setData('initialAlternativeTitle', $initialAlternativeTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전LayerMobileSendSaveSmsTemplateController.php
| { | |
| $request = Request::post()->toArray(); | |
| $contents = $request['contents'] ?? ''; | |
| $categories = SmsTemplateCategory::getFindOptions(); | |
| $this->setData('categories', $categories); | |
| $this->setData('contents', $contents); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 후LayerMobileSendSaveSmsTemplateController.php
| { | |
| $request = Request::post()->toArray(); | |
| $contents = $request['contents'] ?? ''; | |
| $messageTitle = $request['messageTitle'] ?? ''; | |
| $categories = SmsTemplateCategory::getFindOptions(); | |
| $this->setData('categories', $categories); | |
| $this->setData('contents', $contents); | |
| $this->setData('messageTitle', $messageTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 전LayerMyappPushContentSettingController.php
| $initialTitle = $myappRequest['title'] ?? ''; | |
| $initialMessage = $myappRequest['content'] ?? ''; | |
| $initialAlternativeMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('myappPushSendConditions', MyappPushSendCondition::cases()); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerMyappPushContentSettingController.php
| $initialTitle = $myappRequest['title'] ?? ''; | |
| $initialMessage = $myappRequest['content'] ?? ''; | |
| $initialAlternativeMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $initialAlternativeTitle = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('myappPushSendConditions', MyappPushSendCondition::cases()); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->setData('initialAlternativeTitle', $initialAlternativeTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전LayerSmsContentSettingController.php
| $recipeContext = $this->resolveRecipeContext(); | |
| $isRecipeContext = $this->hasRecipeContext(); | |
| $initialMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('isRecipeContext', $isRecipeContext); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerSmsContentSettingController.php
| $recipeContext = $this->resolveRecipeContext(); | |
| $isRecipeContext = $this->hasRecipeContext(); | |
| $initialMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $initialTitle = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('isRecipeContext', $isRecipeContext); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전SmsTemplatePsController.php
| 'templateCategory' => $category->value, | |
| 'templateTitle' => $subject, | |
| 'templateMessageContent' => $contents, | |
| ]); | |
| $sno = $service->setSmsContents($templateDto); | |
변경 후SmsTemplatePsController.php
| 'templateCategory' => $category->value, | |
| 'templateTitle' => $subject, | |
| 'templateMessageContent' => $contents, | |
| 'templateMessageTitle' => trim($request['messageTitle'] ?? ''), | |
| ]); | |
| $sno = $service->setSmsContents($templateDto); | |
변경 전SmsAutoController.php
| // SMS 포인트 Sync | |
| Sms::saveSmsPoint(); | |
| $memberJoin = ComponentUtils::getPolicy('member.join'); | |
| $this->setData('smsAutoList', Sms::SMS_AUTO_RECEIVE_LIST); | |
| $this->setData('smsAutoOrderPeriod', Sms::SMS_AUTO_ORDER_PERIOD); | |
| $this->setData('smsAutoOrderAfterPeriod', Sms::SMS_ORDER_AFTER_PERIOD); | |
변경 후SmsAutoController.php
| // SMS 포인트 Sync | |
| Sms::saveSmsPoint(); | |
| $memberJoin = ComponentUtils::getPolicy('member.join'); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsAutoList', Sms::SMS_AUTO_RECEIVE_LIST); | |
| $this->setData('smsAutoOrderPeriod', Sms::SMS_AUTO_ORDER_PERIOD); | |
| $this->setData('smsAutoOrderAfterPeriod', Sms::SMS_ORDER_AFTER_PERIOD); | |
변경 전SmsLogPsController.php
| try { | |
| $requestParams = $request->post()->all(); | |
| $godoSms = new GodoSmsServerApi(); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $requestParams['smsLogSno']); | |
| if ($smsLog['replaceCodeType'] == 'none') { | |
| // SMS 결과 수신 처리 | |
| if ($godoSms->smsReserveChange($requestParams['sno'], 'modify', $requestParams['contents']) !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } else { | |
| $componentSmsLog->editContents($requestParams); | |
| $this->json(__('수정되었습니다.')); | |
| } | |
| } else { | |
| // SMS 결과 수신 처리 | |
| if ($godoSms->smsSendListReserveChange($requestParams['sno'], 'modify', $requestParams['contents']) !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } else { | |
| $componentSmsLog->editContents($requestParams); | |
| $this->json(__('수정되었습니다.')); | |
| } | |
| } | |
| } catch (LayerException $e) { | |
| $this->json($e->getMessage()); | |
| } | |
변경 후SmsLogPsController.php
| try { | |
| $requestParams = $request->post()->all(); | |
| $godoSms = new GodoSmsServerApi(); | |
| // 발송내역 고유번호 (수정 레이어는 sno 로 전달) | |
| $smsLogSno = gd_isset($requestParams['smsLogSno'], gd_isset($requestParams['sno'])); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $smsLogSno); | |
| if (empty($smsLog)) { | |
| throw new LayerException(__('발송내역을 찾을 수 없습니다.')); | |
| } | |
| // 예약변경 API 는 DB 의 contents/subject 를 읽어 외부(고도 SMS 서버)로 전송하므로 | |
| // 외부 예약 메시지에 수정 내용이 반영되도록 DB 를 먼저 갱신한다. | |
| $requestParams['sno'] = $smsLogSno; | |
| $componentSmsLog->editContents($requestParams); | |
| if ($smsLog['replaceCodeType'] == 'none') { | |
| $result = $godoSms->smsReserveChange($smsLogSno, 'modify'); | |
| } else { | |
| // 치환코드 발송건은 수신자별로 재구성되므로 해당 발송내역의 발송리스트 sno 목록을 전달한다. | |
| $smsSendList = $componentSmsLog->getSmsSendList(['smsLogSno' => $smsLogSno]); | |
| $sendListSno = []; | |
| foreach ((array) gd_isset($smsSendList['data'], []) as $sendListRow) { | |
| $sendListSno[] = $sendListRow['sno']; | |
| } | |
| $result = $godoSms->smsSendListReserveChange($smsLogSno, 'modify', $sendListSno); | |
| } | |
| if ($result !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } | |
| $this->json(__('수정되었습니다.')); | |
| } catch (LayerException $e) { | |
| $this->json($e->getMessage()); | |
| } | |
변경 전SmsSendController.php
| 'board' => '게시판', | |
| ]; | |
| $smsContents = ''; | |
| $receiveTotal = $rejectCount = 0; | |
| $receiverData = $reSenderData = []; | |
| $popupMode = false; | |
| $componentSmsLog = \App::load('Component\\Sms\\SmsLog'); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $request->post()->get('smsLogSno')); // 재전송 문자내역 조회 | |
| $smsContents = StringUtils::htmlSpecialCharsStripSlashes($smsLog['contents']); // 재전송 메시지 설정 | |
| $smsSendList = $componentSmsLog->getSmsSendList($request->post()->all())['data']; // 재전송 문자내역 발송내역 조회 | |
| $hasGuest = $componentSmsLog->hasGuestBySendList($smsSendList); // 발송내역 중 비회원 발송내역 확인 | |
| $isReSendAll = $request->post()->get('mode', '') == 'resend_all_member'; | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('smsCallNum', $smsCallNum); | |
| $this->setData('receiverMode', $receiverMode); | |
| $this->setData('popupMode', $popupMode); | |
| $this->setData('smsContents', $smsContents); | |
| $this->setData('reSenderData', $reSenderData); | |
| $this->setData('receiveTotal', $receiveTotal); | |
| $this->setData('rejectCount', $rejectCount); | |
변경 후SmsSendController.php
| 'board' => '게시판', | |
| ]; | |
| $smsContents = ''; | |
| $smsSubject = ''; | |
| $receiveTotal = $rejectCount = 0; | |
| $receiverData = $reSenderData = []; | |
| $popupMode = false; | |
| $componentSmsLog = \App::load('Component\\Sms\\SmsLog'); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $request->post()->get('smsLogSno')); // 재전송 문자내역 조회 | |
| $smsContents = StringUtils::htmlSpecialCharsStripSlashes($smsLog['contents']); // 재전송 메시지 설정 | |
| $smsSubject = StringUtils::htmlSpecialCharsStripSlashes($smsLog['subject'] ?? ''); // 재전송 LMS 제목 복원 | |
| $smsSendList = $componentSmsLog->getSmsSendList($request->post()->all())['data']; // 재전송 문자내역 발송내역 조회 | |
| $hasGuest = $componentSmsLog->hasGuestBySendList($smsSendList); // 발송내역 중 비회원 발송내역 확인 | |
| $isReSendAll = $request->post()->get('mode', '') == 'resend_all_member'; | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('smsCallNum', $smsCallNum); | |
| $this->setData('receiverMode', $receiverMode); | |
| $this->setData('popupMode', $popupMode); | |
| $this->setData('smsContents', $smsContents); | |
| $this->setData('smsSubject', $smsSubject); | |
| $this->setData('reSenderData', $reSenderData); | |
| $this->setData('receiveTotal', $receiveTotal); | |
| $this->setData('rejectCount', $rejectCount); | |
변경 전CartRemindRegistController.php
| $this->setData('selected', $selected); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('commerceSmsRefusalIntroUrl', ConfigUrlUtils::getNhnCommerceEchostUrl('sms-refusal-intro')); | |
변경 후CartRemindRegistController.php
| $this->setData('selected', $selected); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('commerceSmsRefusalIntroUrl', ConfigUrlUtils::getNhnCommerceEchostUrl('sms-refusal-intro')); | |
변경 전ComebackCouponRegistController.php
| ]); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('checkMode', gd_isset($checkMode)); | |
변경 후ComebackCouponRegistController.php
| ]); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('checkMode', gd_isset($checkMode)); | |
변경 전LayerCartRemindMessageController.php
| { | |
| $cartRemindNo = Request::get()->get('cartRemindNo'); | |
| $cartRemind = new CartRemind(); | |
| $cartRemindData = $cartRemind->getCartRemindInfo($cartRemindNo,'cartRemindNo, cartRemindSendType, cartRemindSendMessage'); | |
| $this->setData('cartRemindData', $cartRemindData); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 후LayerCartRemindMessageController.php
| { | |
| $cartRemindNo = Request::get()->get('cartRemindNo'); | |
| $cartRemind = new CartRemind(); | |
| $cartRemindData = $cartRemind->getCartRemindInfo($cartRemindNo,'cartRemindNo, cartRemindSendType, cartRemindSendMessage, cartRemindSendSubject'); | |
| $this->setData('cartRemindData', $cartRemindData); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 전LayerStandbySmsController.php
| { | |
| /** @var \Bundle\Component\Sms\SmsLog $smsLog */ | |
| $smsLog = App::load('\\Component\\Sms\\SmsLog'); | |
| $data = $smsLog->getSmsLog('sno, sendFl, contents, contentsMask', Request::get()->get('sno')); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| $this->setData('data', gd_htmlspecialchars_stripslashes($data)); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| } | |
변경 후LayerStandbySmsController.php
| { | |
| /** @var \Bundle\Component\Sms\SmsLog $smsLog */ | |
| $smsLog = App::load('\\Component\\Sms\\SmsLog'); | |
| $data = $smsLog->getSmsLog('sno, sendFl, subject, contents, contentsMask', Request::get()->get('sno')); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| $this->setData('data', gd_htmlspecialchars_stripslashes($data)); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| } | |
변경 전OrderAdminNew.php
| use Framework\Debug\Exception\LayerNotReloadException; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\WarningException; | |
| use Framework\StaticProxy\Proxy\UserFilePath; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| $this->checked['useFl'][$this->search['useFl']] = 'checked="checked"'; | |
| // 키워드 검색 | |
| if ($this->search['keyword']) { | |
| if ($this->search['key'] == '') { | |
| $tmpWhere = [ | |
| 'bankName', | |
| 'accountNumber', | |
| 'depositor', | |
| ]; | |
| $arrWhereAll = []; | |
| foreach ($tmpWhere as $keyNm) { | |
| $arrWhereAll[] = '(' . $keyNm . ' LIKE concat(\'%\',?,\'%\'))'; | |
| $this->db->bind_param_push($this->arrBind, 's', $this->search['keyword']); | |
| } | |
| $this->arrWhere[] = '(' . gd_implode(' OR ', $arrWhereAll) . ')'; | |
| } else { | |
| $this->arrWhere[] = '' . $this->search['key'] . ' LIKE concat(\'%\',?,\'%\')'; | |
| $this->db->bind_param_push($this->arrBind, 's', $this->search['keyword']); | |
| } | |
| } | |
| // 사용 여부 검색 | |
| if ($this->search['useFl']) { | |
| $this->arrWhere[] = 'useFl = ?'; | |
| $page->setPage(); | |
| $page->setUrl(\Request::getQueryString()); | |
| // 현 페이지 결과 | |
| $this->db->strField = '*'; | |
| $this->db->strWhere = gd_implode(' AND ', gd_isset($this->arrWhere)); | |
| $this->db->strOrder = "defaultFl desc," . $this->search['sort']; | |
| $this->db->strLimit = $page->recode['start'] . ',' . $request['pageNum']; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = $this->db->query_fetch($strSQL, $this->arrBind); | |
| // 레코드 수 | |
| unset($query['group'], $query['order'], $query['limit']); | |
| $strCntSQL = 'SELECT COUNT(*) AS total FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $page->recode['total'] = $this->db->query_fetch($strCntSQL, $this->arrBind, false)['total']; | |
| //list($page->recode['total']) = $this->db->fetch('SELECT FOUND_ROWS()', 'row'); | |
| $page->setPage(); | |
| // 각 데이터 배열화 | |
| $getData['data'] = gd_htmlspecialchars_stripslashes(gd_isset($data)); | |
| throw new Exception(__('예금주은(는) 필수 항목 입니다.')); | |
| } | |
| if (empty($arrData['defaultFl']) === true) { | |
| $arrData['defaultFl'] = "n"; | |
| } | |
변경 후OrderAdminNew.php
| use Framework\Debug\Exception\LayerNotReloadException; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\WarningException; | |
| use Framework\Security\ManageBankCryptor; | |
| use Framework\StaticProxy\Proxy\UserFilePath; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| $this->checked['useFl'][$this->search['useFl']] = 'checked="checked"'; | |
| // 사용 여부 검색 | |
| if ($this->search['useFl']) { | |
| $this->arrWhere[] = 'useFl = ?'; | |
| $page->setPage(); | |
| $page->setUrl(\Request::getQueryString()); | |
| $this->db->strField = '*'; | |
| $this->db->strWhere = gd_implode(' AND ', gd_isset($this->arrWhere)); | |
| $this->db->strOrder = "defaultFl desc," . $this->search['sort']; | |
| $keyword = (string) $this->search['keyword']; | |
| if ($keyword !== '') { | |
| // 계좌번호는 암호화 저장되어 SQL 조건 검색이 불가하므로, 전체 목록을 조회·복호화 후 검색 항목(은행명·계좌번호·예금주) 기준으로 필터한다. | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = gd_isset($this->db->query_fetch($strSQL, $this->arrBind), []); | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| // 검색 항목 기준으로 키워드 부분검색 필터 | |
| $data = $this->filterBankListByKeyword($data, $keyword, (string) $this->search['key'], false); | |
| $page->recode['total'] = count($data); | |
| $page->setPage(); | |
| $data = array_slice($data, $page->recode['start'], (int) $request['pageNum']); | |
| } else { | |
| $this->db->strLimit = $page->recode['start'] . ',' . $request['pageNum']; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = $this->db->query_fetch($strSQL, $this->arrBind); | |
| // 계좌번호 복호화 | |
| if (!empty($data)) { | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| } | |
| // 레코드 수 | |
| unset($query['group'], $query['order'], $query['limit']); | |
| $strCntSQL = 'SELECT COUNT(*) AS total FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $page->recode['total'] = $this->db->query_fetch($strCntSQL, $this->arrBind, false)['total']; | |
| $page->setPage(); | |
| } | |
| // 각 데이터 배열화 | |
| $getData['data'] = gd_htmlspecialchars_stripslashes(gd_isset($data)); | |
| throw new Exception(__('예금주은(는) 필수 항목 입니다.')); | |
| } | |
| // 계좌번호 암호화 저장 | |
| $arrData['accountNumber'] = ManageBankCryptor::encrypt($arrData['accountNumber']); | |
| if (empty($arrData['defaultFl']) === true) { | |
| $arrData['defaultFl'] = "n"; | |
| } | |
변경 전OrderAdmin.php
| use Framework\Debug\Exception\LayerNotReloadException; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\WarningException; | |
| use Framework\StaticProxy\Proxy\UserFilePath; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| $this->checked['useFl'][$this->search['useFl']] = 'checked="checked"'; | |
| // 키워드 검색 | |
| if ($this->search['keyword']) { | |
| if ($this->search['key'] == '') { | |
| $tmpWhere = [ | |
| 'bankName', | |
| 'accountNumber', | |
| 'depositor', | |
| ]; | |
| $arrWhereAll = []; | |
| foreach ($tmpWhere as $keyNm) { | |
| if ($this->search['searchKind'] == 'equalSearch') { | |
| $arrWhereAll[] = '(' . $keyNm . ' = ? )'; | |
| } else { | |
| $arrWhereAll[] = '(' . $keyNm . ' LIKE concat(\'%\',?,\'%\'))'; | |
| } | |
| $this->db->bind_param_push($this->arrBind, 's', $this->search['keyword']); | |
| } | |
| $this->arrWhere[] = '(' . gd_implode(' OR ', $arrWhereAll) . ')'; | |
| } else { | |
| if ($this->search['searchKind'] == 'equalSearch') { | |
| $this->arrWhere[] = '' . $this->search['key'] . ' = ? '; | |
| } else { | |
| $this->arrWhere[] = '' . $this->search['key'] . ' LIKE concat(\'%\',?,\'%\')'; | |
| } | |
| $this->db->bind_param_push($this->arrBind, 's', $this->search['keyword']); | |
| } | |
| } | |
| // 사용 여부 검색 | |
| if ($this->search['useFl']) { | |
| $this->arrWhere[] = 'useFl = ?'; | |
| $page->setPage(); | |
| $page->setUrl(\Request::getQueryString()); | |
| // 현 페이지 결과 | |
| $this->db->strField = '*'; | |
| $this->db->strWhere = gd_implode(' AND ', gd_isset($this->arrWhere)); | |
| $this->db->strOrder = "defaultFl desc," . $this->search['sort']; | |
| $this->db->strLimit = $page->recode['start'] . ',' . $request['pageNum']; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = $this->db->query_fetch($strSQL, $this->arrBind); | |
| // 레코드 수 | |
| unset($query['group'], $query['order'], $query['limit']); | |
| $strCntSQL = 'SELECT COUNT(*) AS total FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $page->recode['total'] = $this->db->query_fetch($strCntSQL, $this->arrBind, false)['total']; | |
| //list($page->recode['total']) = $this->db->fetch('SELECT FOUND_ROWS()', 'row'); | |
| $page->setPage(); | |
| // 각 데이터 배열화 | |
| $getData['data'] = gd_htmlspecialchars_stripslashes(gd_isset($data)); | |
| return $getData; | |
| } | |
| /** | |
| * 주문정책내 무통장 입금은행 등록 / 수정 | |
| * | |
| throw new Exception(__('예금주은(는) 필수 항목 입니다.')); | |
| } | |
| if (empty($arrData['defaultFl']) === true) { | |
| $arrData['defaultFl'] = "n"; | |
| } | |
변경 후OrderAdmin.php
| use Framework\Debug\Exception\LayerNotReloadException; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\WarningException; | |
| use Framework\Security\ManageBankCryptor; | |
| use Framework\StaticProxy\Proxy\UserFilePath; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| $this->checked['useFl'][$this->search['useFl']] = 'checked="checked"'; | |
| // 사용 여부 검색 | |
| if ($this->search['useFl']) { | |
| $this->arrWhere[] = 'useFl = ?'; | |
| $page->setPage(); | |
| $page->setUrl(\Request::getQueryString()); | |
| $this->db->strField = '*'; | |
| $this->db->strWhere = gd_implode(' AND ', gd_isset($this->arrWhere)); | |
| $this->db->strOrder = "defaultFl desc," . $this->search['sort']; | |
| $keyword = (string) $this->search['keyword']; | |
| if ($keyword !== '') { | |
| // 계좌번호는 암호화 저장되어 SQL 조건 검색이 불가하므로, 전체 목록을 조회·복호화 후 검색 항목(은행명·계좌번호·예금주) 기준으로 필터한다. | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = gd_isset($this->db->query_fetch($strSQL, $this->arrBind), []); | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| // 검색 항목 기준으로 키워드 필터 | |
| $data = $this->filterBankListByKeyword($data, $keyword, (string) $this->search['key'], $this->search['searchKind'] == 'equalSearch'); | |
| $page->recode['total'] = count($data); | |
| $page->setPage(); | |
| $data = array_slice($data, $page->recode['start'], (int) $request['pageNum']); | |
| } else { | |
| $this->db->strLimit = $page->recode['start'] . ',' . $request['pageNum']; | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $data = $this->db->query_fetch($strSQL, $this->arrBind); | |
| // 계좌번호 복호화 | |
| if (!empty($data)) { | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| } | |
| // 레코드 수 | |
| unset($query['group'], $query['order'], $query['limit']); | |
| $strCntSQL = 'SELECT COUNT(*) AS total FROM ' . DB_MANAGE_BANK . gd_implode(' ', $query); | |
| $page->recode['total'] = $this->db->query_fetch($strCntSQL, $this->arrBind, false)['total']; | |
| $page->setPage(); | |
| } | |
| // 각 데이터 배열화 | |
| $getData['data'] = gd_htmlspecialchars_stripslashes(gd_isset($data)); | |
| return $getData; | |
| } | |
| /** | |
| * 무통장 입금은행 목록을 검색어(은행명·계좌번호·예금주) 기준으로 필터링 | |
| * | |
| * @param array $data 복호화 완료된 은행 목록 | |
| * @param string $keyword 검색어 | |
| * @param string $key 검색 항목 (빈 값이면 통합검색: 은행명·계좌번호·예금주) | |
| * @param bool $isEqual 완전일치 여부 (false 면 부분검색) | |
| * | |
| * @return array 필터링된 목록 (인덱스 재정렬) | |
| */ | |
| protected function filterBankListByKeyword(array $data, string $keyword, string $key, bool $isEqual): array | |
| { | |
| $fields = $key === '' ? ['bankName', 'accountNumber', 'depositor'] : [$key]; | |
| return array_values(array_filter($data, function ($row) use ($fields, $keyword, $isEqual) { | |
| foreach ($fields as $field) { | |
| $target = (string) $row[$field]; | |
| if ($isEqual ? $target === $keyword : mb_strpos($target, $keyword) !== false) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| })); | |
| } | |
| /** | |
| * 주문정책내 무통장 입금은행 등록 / 수정 | |
| * | |
| throw new Exception(__('예금주은(는) 필수 항목 입니다.')); | |
| } | |
| // 계좌번호 암호화 저장 | |
| $arrData['accountNumber'] = ManageBankCryptor::encrypt($arrData['accountNumber']); | |
| if (empty($arrData['defaultFl']) === true) { | |
| $arrData['defaultFl'] = "n"; | |
| } | |
변경 전OrderNew.php
| use Framework\Helper\MallHelper; | |
| use Framework\SimpleCache\SimpleCache; | |
| use Framework\SimpleCache\SimpleCacheException; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\KafkaUtils; | |
| if (empty($data) === true) { | |
| return false; | |
| } else { | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
| } | |
| $strSQL = 'SELECT sno, ' . gd_implode(', ', DBTableField::setTableField('tableManageBank')) . ' FROM ' . DB_MANAGE_BANK . ' WHERE ' . gd_implode(' AND ', $arrWhere); | |
| $data = $this->db->query_fetch($strSQL, $arrBind, $boolFetch); | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
변경 후OrderNew.php
| use Framework\Helper\MallHelper; | |
| use Framework\SimpleCache\SimpleCache; | |
| use Framework\SimpleCache\SimpleCacheException; | |
| use Framework\Security\ManageBankCryptor; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\KafkaUtils; | |
| if (empty($data) === true) { | |
| return false; | |
| } else { | |
| // 계좌번호 복호화 | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
| } | |
| $strSQL = 'SELECT sno, ' . gd_implode(', ', DBTableField::setTableField('tableManageBank')) . ' FROM ' . DB_MANAGE_BANK . ' WHERE ' . gd_implode(' AND ', $arrWhere); | |
| $data = $this->db->query_fetch($strSQL, $arrBind, $boolFetch); | |
| // 계좌번호 복호화 | |
| if ($boolFetch) { | |
| if (!empty($data)) { | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| } | |
| } else { | |
| if (!empty($data['accountNumber'])) { | |
| $data['accountNumber'] = ManageBankCryptor::decrypt($data['accountNumber']); | |
| } | |
| } | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
변경 전Order.php
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\DatabaseException; | |
| use Framework\Helper\MallHelper; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\NumberUtils; | |
| if (empty($data) === true) { | |
| return false; | |
| } else { | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
| } | |
| $strSQL = 'SELECT sno, ' . gd_implode(', ', DBTableField::setTableField('tableManageBank')) . ' FROM ' . DB_MANAGE_BANK . ' WHERE ' . gd_implode(' AND ', $arrWhere); | |
| $data = $this->db->secondary()->query_fetch($strSQL, $arrBind, $boolFetch); | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
변경 후Order.php
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Framework\Debug\Exception\DatabaseException; | |
| use Framework\Helper\MallHelper; | |
| use Framework\Security\ManageBankCryptor; | |
| use Framework\Utility\ArrayUtils; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\NumberUtils; | |
| if (empty($data) === true) { | |
| return false; | |
| } else { | |
| // 계좌번호 복호화 | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
| } | |
| $strSQL = 'SELECT sno, ' . gd_implode(', ', DBTableField::setTableField('tableManageBank')) . ' FROM ' . DB_MANAGE_BANK . ' WHERE ' . gd_implode(' AND ', $arrWhere); | |
| $data = $this->db->secondary()->query_fetch($strSQL, $arrBind, $boolFetch); | |
| // 계좌번호 복호화 | |
| if ($boolFetch) { | |
| if (!empty($data)) { | |
| foreach ($data as $index => $bankInfo) { | |
| $data[$index]['accountNumber'] = ManageBankCryptor::decrypt($bankInfo['accountNumber']); | |
| } | |
| } | |
| } else { | |
| if (!empty($data['accountNumber'])) { | |
| $data['accountNumber'] = ManageBankCryptor::decrypt($data['accountNumber']); | |
| } | |
| } | |
| return gd_htmlspecialchars_stripslashes($data); | |
| } | |
변경 전SecureSocketLayer.php
| $checkData = $this->getSsl($searchArr); | |
| if (gd_count($checkData) > 0) { | |
| $returnData['status'] = 'usePay'; | |
| } else if ($this->getFreeSslUse()) { | |
| $returnData['status'] = 'used'; | |
| } else { | |
| $returnData['status'] = 'process'; | |
| $isValidPeriod = ($sDateCheck >= 0 && $eDateCheck >= 0); // 설치완료 | |
| if ($isExpired) { | |
| $returnData['status'] = 'request'; | |
| } else if ($isRenewRange) { | |
| if (gd_in_array($sslData['sslConfigStatus'], ['wait', 'process']) === true) { | |
| $returnData['status'] = $sslData['sslConfigStatus']; | |
| } else if ($sslData['sslConfigType'] == 'godo') { | |
| $returnData['status'] = 'renewrequest'; | |
| } | |
| } else if ($isValidPeriod) { | |
| $returnData['status'] = 'used'; | |
| } else { | |
| $returnData['status'] = $sslData['sslConfigStatus']; | |
변경 후SecureSocketLayer.php
| $checkData = $this->getSsl($searchArr); | |
| if (gd_count($checkData) > 0) { | |
| $returnData['status'] = 'usePay'; | |
| } elseif ($this->getFreeSslUse()) { | |
| $returnData['status'] = 'used'; | |
| } else { | |
| $returnData['status'] = 'process'; | |
| $isValidPeriod = ($sDateCheck >= 0 && $eDateCheck >= 0); // 설치완료 | |
| if ($isExpired) { | |
| $returnData['status'] = 'request'; | |
| } elseif ($isRenewRange) { | |
| if (gd_in_array($sslData['sslConfigStatus'], ['wait', 'process']) === true) { | |
| $returnData['status'] = $sslData['sslConfigStatus']; | |
| } elseif ($sslData['sslConfigType'] == 'godo') { | |
| $returnData['status'] = 'renewrequest'; | |
| } elseif ($sslData['sslConfigType'] === 'free_multi') { | |
| $returnData['status'] = 'used'; | |
| } | |
| } elseif ($isValidPeriod) { | |
| $returnData['status'] = 'used'; | |
| } else { | |
| $returnData['status'] = $sslData['sslConfigStatus']; | |
변경 전owned_skin_list_section.php
| <header class="ncua-card__header"> | |
| <h4 class="ncua-card__title">보유 스킨 리스트</h4> | |
| </header> | |
| <!-- 탭 영역 --> | |
| <?php if ($skinTabData['responsiveSkinCount'] > 0 && $skinTabData['adaptiveSkinCount'] > 0): ?> | |
| <div class="swiper ncua-horizontal-tab ncua-horizontal-tab--sm ncua-horizontal-tab--underline-fill"> | |
| <div class="swiper-wrapper ncua-gap-8"> | |
| <div class="swiper-slide ncua-horizontal-tab__item"> | |
| </div> | |
| </div> | |
| </div> | |
| <?php endif; ?> | |
| </div> | |
| <section class="ncua-card__body"> | |
| <p class="ncua-search-result__summary-count"> | |
| 전체 <strong class="js-total-count">0</strong>개 | |
| </p> | |
| <!-- TODO: 반응형 스킨이 있는 경우 is-visible-hidden 클래스 추가 --> | |
| <div class="ncua-file-input ncua-file-input--xs"> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray js-skin-upload <?= $skinTabData['defaultTab'] === 'responsive' ? 'is-visible-hidden' : '' ?>"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="none" class="ncua-btn__icon"> | |
변경 후owned_skin_list_section.php
| <header class="ncua-card__header"> | |
| <h4 class="ncua-card__title">보유 스킨 리스트</h4> | |
| </header> | |
| <!-- 탭 영역 (스킨 보유 여부와 무관하게 항상 노출) --> | |
| <div class="swiper ncua-horizontal-tab ncua-horizontal-tab--sm ncua-horizontal-tab--underline-fill"> | |
| <div class="swiper-wrapper ncua-gap-8"> | |
| <div class="swiper-slide ncua-horizontal-tab__item"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <section class="ncua-card__body"> | |
| <p class="ncua-search-result__summary-count"> | |
| 전체 <strong class="js-total-count">0</strong>개 | |
| </p> | |
| <!-- 스킨 업로드: 반응형 탭 미노출, PC/모바일 탭 노출 (탭 전환 시 JS에서 토글) --> | |
| <div class="ncua-file-input ncua-file-input--xs"> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--secondary-gray js-skin-upload <?= $skinTabData['defaultTab'] === 'responsive' ? 'is-visible-hidden' : '' ?>"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="none" class="ncua-btn__icon"> | |
변경 전design_skin_list.php
| <script type="text/javascript" src="<?=gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/ncua-dropdown-wrapper.v0.1.js')?>"></script> | |
| <script defer src="<?= gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/spinner-modal.js') ?>"></script> | |
| <article class="ncua-content design-skin-list"> | |
| <header class="page-header ncua-page-header js-affix"> | |
| <h3 class="ncua-help-manual"><?= end($naviMenu->location); ?> | |
| </h3> | |
| <?php include $activeDesignSkinSection; ?> | |
| <?php } ?> | |
| <!-- 보유 스킨 리스트 --> | |
| <?php if ($skinTabData['responsiveSkinCount'] > 0 || $skinTabData['adaptiveSkinCount'] > 0) { ?> | |
| <?php include $ownedSkinListSection; ?> | |
| <?php } ?> | |
| <!-- 해외몰 홈아이콘 설정 --> | |
| <?php if ($mallCnt > 1) { ?> | |
| // 모두 보기 버튼 표시 여부 업데이트 | |
| ownedSkinList.updateViewAllButton(filteredList.length); | |
| filteredList.forEach((skin, idx) => { | |
| try { | |
| if(maxLen && maxLen <= idx) return; | |
변경 후design_skin_list.php
| <script type="text/javascript" src="<?=gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/ncua-dropdown-wrapper.v0.1.js')?>"></script> | |
| <script defer src="<?= gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/spinner-modal.js') ?>"></script> | |
| <article class="ncua-content design-skin-list content-wrap-initial"> | |
| <header class="page-header ncua-page-header js-affix"> | |
| <h3 class="ncua-help-manual"><?= end($naviMenu->location); ?> | |
| </h3> | |
| <?php include $activeDesignSkinSection; ?> | |
| <?php } ?> | |
| <!-- 보유 스킨 리스트 (스킨 보유 여부와 무관하게 항상 노출) --> | |
| <?php include $ownedSkinListSection; ?> | |
| <!-- 해외몰 홈아이콘 설정 --> | |
| <?php if ($mallCnt > 1) { ?> | |
| // 모두 보기 버튼 표시 여부 업데이트 | |
| ownedSkinList.updateViewAllButton(filteredList.length); | |
| // 보유 스킨이 없는 경우 안내 문구 노출 | |
| if (filteredList.length === 0) { | |
| const emptyMessage = document.createElement('div'); | |
| emptyMessage.className = 'owned-skin-list--empty'; | |
| emptyMessage.textContent = '보유한 스킨이 없습니다.'; | |
| skinList.appendChild(emptyMessage); | |
| return; | |
| } | |
| filteredList.forEach((skin, idx) => { | |
| try { | |
| if(maxLen && maxLen <= idx) return; | |
변경 전DesignSkinListController.php
| use Origin\Service\Aggregator\GodomallAggregatorService; | |
| use Origin\Service\MyApp\MyappSettingService; | |
| use Origin\Enum\ManagerTutorialType; | |
| use Origin\Service\Admin\Member\ManagerTutorial\HelperPopupExposureAvailabilityService; | |
| // 스킨 설정 정보, (사용 중 아닌) 스킨 목록 설정 | |
| $designSkinConfig = gd_policy('design.skin', $mallSno); | |
| $usingSkinType = $designSkinConfig['skinType'] ?? 'adaptive'; | |
| // 모바일샵 설정 정보 | |
| $mobileConfig = gd_policy('mobile.config'); | |
| $unusedSkinList = []; | |
| foreach ($skinList as $skin) { | |
| $skinType = $skin['skin_type'] ?? 'adaptive'; | |
| $skinDevice = $skin['skin_device']; | |
| $skinCode = $skin['skin_code']; | |
| // 적응형 스킨에만 default_design_page_id 추가 | |
| if ($skinType === 'adaptive') { | |
| $skin['default_design_page_id'] = $this->getDefaultDesignPageId($skinCode, $skinDevice); | |
| } | |
| $adaptiveSkinCount = 0; | |
| foreach ($skinList as $skin) { | |
| if (($skin['skin_type'] ?? 'adaptive') === 'responsive') { | |
| $responsiveSkinCount++; | |
| } else { | |
| $adaptiveSkinCount++; | |
| } | |
| } | |
| // 기본 탭 결정: 둘 다 있으면 사용 중인 타입, 아니면 보유한 타입 | |
| if ($responsiveSkinCount > 0 && $adaptiveSkinCount > 0) { | |
| $defaultTab = $usingSkinType; | |
| } elseif ($responsiveSkinCount > 0) { | |
| $defaultTab = 'responsive'; | |
| } else { | |
| $defaultTab = 'adaptive'; | |
| } | |
| return [ | |
| 'responsiveSkinCount' => $responsiveSkinCount, | |
| 'adaptiveSkinCount' => $adaptiveSkinCount, | |
| 'isResponsiveActive' => $usingSkinType === 'responsive', | |
| 'isAdaptiveActive' => $usingSkinType !== 'responsive', | |
| 'defaultTab' => $defaultTab, | |
| ]; | |
| } | |
변경 후DesignSkinListController.php
| use Origin\Service\Aggregator\GodomallAggregatorService; | |
| use Origin\Service\MyApp\MyappSettingService; | |
| use Origin\Enum\ManagerTutorialType; | |
| use Origin\Enum\Design\DesignEditorSkinType; | |
| use Origin\Service\Admin\Member\ManagerTutorial\HelperPopupExposureAvailabilityService; | |
| // 스킨 설정 정보, (사용 중 아닌) 스킨 목록 설정 | |
| $designSkinConfig = gd_policy('design.skin', $mallSno); | |
| $usingSkinType = $designSkinConfig['skinType'] ?? DesignEditorSkinType::ADAPTIVE->value; | |
| // 모바일샵 설정 정보 | |
| $mobileConfig = gd_policy('mobile.config'); | |
| $unusedSkinList = []; | |
| foreach ($skinList as $skin) { | |
| $skinType = $skin['skin_type'] ?? DesignEditorSkinType::ADAPTIVE->value; | |
| $skinDevice = $skin['skin_device']; | |
| $skinCode = $skin['skin_code']; | |
| // 적응형 스킨에만 default_design_page_id 추가 | |
| if ($skinType === DesignEditorSkinType::ADAPTIVE->value) { | |
| $skin['default_design_page_id'] = $this->getDefaultDesignPageId($skinCode, $skinDevice); | |
| } | |
| $adaptiveSkinCount = 0; | |
| foreach ($skinList as $skin) { | |
| if (($skin['skin_type'] ?? DesignEditorSkinType::ADAPTIVE->value) === DesignEditorSkinType::RESPONSIVE->value) { | |
| $responsiveSkinCount++; | |
| } else { | |
| $adaptiveSkinCount++; | |
| } | |
| } | |
| // 탭은 스킨 보유 여부와 무관하게 항상 노출되므로, 기본 탭은 현재 사용 중인 스킨 유형을 따른다. | |
| $isResponsiveActive = $usingSkinType === DesignEditorSkinType::RESPONSIVE->value; | |
| $defaultTab = $isResponsiveActive ? DesignEditorSkinType::RESPONSIVE->value : DesignEditorSkinType::ADAPTIVE->value; | |
| return [ | |
| 'responsiveSkinCount' => $responsiveSkinCount, | |
| 'adaptiveSkinCount' => $adaptiveSkinCount, | |
| 'isResponsiveActive' => $isResponsiveActive, | |
| 'isAdaptiveActive' => !$isResponsiveActive, | |
| 'defaultTab' => $defaultTab, | |
| ]; | |
| } | |
변경 전base_seo.php
| <tr> | |
| <th>모바일 쇼핑몰</th> | |
| <td class="form-inline"> | |
| <?php echo URI_MOBILE;?><input type="text" name="errPage[mobile]" value="<?php echo $data['errPage']['mobile']; ?>" class="form-control width-lg"/> | |
| </td> | |
| </tr> | |
| </table> | |
변경 후base_seo.php
| <tr> | |
| <th>모바일 쇼핑몰</th> | |
| <td class="form-inline"> | |
| <?=$data['mallMobileDomain'] ?? URI_MOBILE?><input type="text" name="errPage[mobile]" value="<?php echo $data['errPage']['mobile']; ?>" class="form-control width-lg"/> | |
| </td> | |
| </tr> | |
| </table> | |
변경 전Mall.php
| const GLOBAL_MALL_BASE_INFO = [ | |
| 'mallNmEng', | |
| 'mallFavicon', | |
| 'mallDomain', | |
| 'mallCategory', | |
| 'businessNo', | |
| 'service', | |
변경 후Mall.php
| const GLOBAL_MALL_BASE_INFO = [ | |
| 'mallNmEng', | |
| 'mallFavicon', | |
| 'mallCategory', | |
| 'businessNo', | |
| 'service', | |
변경 전BaseInfoController.php
| if (gd_in_array($key, Mall::GLOBAL_MALL_BASE_INFO) === true) $data[$key] = $value; | |
| } | |
| $this->setData('disabled', self::ELEMENT_DISABLED); | |
| $this->setData('readonly', self::ELEMENT_READONLY); | |
| } | |
변경 후BaseInfoController.php
| if (gd_in_array($key, Mall::GLOBAL_MALL_BASE_INFO) === true) $data[$key] = $value; | |
| } | |
| //설정한 shopDomain 있으면 덮어쓰기 | |
| if (!empty($globalsInfo[$mallSno]['connectDomain'])) { | |
| $globalShopDomains = json_decode($globalsInfo[$mallSno]['connectDomain'], true); | |
| $domainIndex = $globalsInfo[$mallSno]['useShopDomain'] ?? null; | |
| if (isset($globalShopDomains['connect'][$domainIndex])) { | |
| $data['mallDomain'] = $globalShopDomains['connect'][$domainIndex]; | |
| } | |
| } | |
| $this->setData('disabled', self::ELEMENT_DISABLED); | |
| $this->setData('readonly', self::ELEMENT_READONLY); | |
| } | |
변경 전BaseSeoController.php
| $socialData = $socialShare->getConfig(); | |
| gd_isset($socialData['snsRepresentTitle'],'{=gMall.mallNm}'); | |
| //RSS 설정 ,페이지 경로 설정 , 대표URL 설정 , 연관채널 설정 | |
| $seoData = gd_policy('basic.seo', $mallSno); | |
변경 후BaseSeoController.php
| $socialData = $socialShare->getConfig(); | |
| gd_isset($socialData['snsRepresentTitle'],'{=gMall.mallNm}'); | |
| //설정한 shopDomain 있으면 덮어쓰기 | |
| $globalsInfo = \Globals::get('gGlobal.mallList'); | |
| if (!empty($globalsInfo[$mallSno]['connectDomain'])) { | |
| $globalShopDomains = json_decode($globalsInfo[$mallSno]['connectDomain'], true); | |
| $domainIndex = $globalsInfo[$mallSno]['useShopDomain'] ?? null; | |
| if (isset($globalShopDomains['connect'][$domainIndex])) { | |
| $data['mallDomain'] = $globalShopDomains['connect'][$domainIndex]; | |
| $data['mallMobileDomain'] = \Request::getDomainUrl(DOMAIN_USEABLE_LIST['mobile'] . '.' . $globalShopDomains['connect'][$domainIndex]) . DS; | |
| } | |
| } | |
| //RSS 설정 ,페이지 경로 설정 , 대표URL 설정 , 연관채널 설정 | |
| $seoData = gd_policy('basic.seo', $mallSno); | |
변경 전IpinApplyController.php
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec("$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| Logger::info(__METHOD__ . '$sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 후IpinApplyController.php
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec( | |
| implode(' ', array_map('escapeshellarg', [$sModulePath, $sType, $sSiteCode, $sSitePw, $sEncData])) | |
| ); | |
| Logger::info(__METHOD__ . '$sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 전IpinResultController.php
| if ($sEncData != "") { | |
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec("$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| Logger::info('sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 후IpinResultController.php
| if ($sEncData != "") { | |
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec( | |
| implode(' ', array_map('escapeshellarg', [$sModulePath, $sType, $sSiteCode, $sSitePw, $sEncData])) | |
| ); | |
| Logger::info('sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 전IpinApplyController.php
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec("$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| Logger::info(__METHOD__ . '$sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 후IpinApplyController.php
| // 사용자 정보를 복호화 합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sDecData = exec( | |
| implode(' ', array_map('escapeshellarg', [$sModulePath, $sType, $sSiteCode, $sSitePw, $sEncData])) | |
| ); | |
| Logger::info(__METHOD__ . '$sDecData=>' . $sDecData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sEncData"); | |
| if ($sDecData == -9) { | |
변경 전IpinMainController.php
| // 앞서 설명드린 바와같이, CP 요청번호는 배포된 모듈을 통해 아래와 같이 생성할 수 있습니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sCPRequest = exec("$sModulePath $sType $sSiteCode", $output, $error); | |
| if ($error !== 0) { | |
| Logger::error(__METHOD__ . ' $sCPRequest=>' . $sCPRequest . ', ' . "$sModulePath $sType $sSiteCode", $output); | |
| } | |
| // 리턴 결과값에 따라, 프로세스 진행여부를 파악합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sEncData = exec("$sModulePath $sType $sSiteCode $sSitePw $sCPRequest $sReturnURL"); | |
| Logger::info(__METHOD__ . ' $sEncData=>' . $sEncData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sCPRequest $sReturnURL"); | |
| // 리턴 결과값에 따른 처리사항 | |
변경 후IpinMainController.php
| // 앞서 설명드린 바와같이, CP 요청번호는 배포된 모듈을 통해 아래와 같이 생성할 수 있습니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sCPRequest = exec( | |
| implode(' ', array_map('escapeshellarg', [$sModulePath, $sType, $sSiteCode])), | |
| $output, | |
| $error | |
| ); | |
| if ($error !== 0) { | |
| Logger::error(__METHOD__ . ' $sCPRequest=>' . $sCPRequest . ', ' . "$sModulePath $sType $sSiteCode", $output); | |
| } | |
| // 리턴 결과값에 따라, 프로세스 진행여부를 파악합니다. | |
| // 실행방법은 싱글쿼터(`) 외에도, 'exec(), system(), shell_exec()' 등등 귀사 정책에 맞게 처리하시기 바랍니다. | |
| $sEncData = exec( | |
| implode(' ', array_map('escapeshellarg', [$sModulePath, $sType, $sSiteCode, $sSitePw, $sCPRequest, $sReturnURL])) | |
| ); | |
| Logger::info(__METHOD__ . ' $sEncData=>' . $sEncData . ', ' . "$sModulePath $sType $sSiteCode $sSitePw $sCPRequest $sReturnURL"); | |
| // 리턴 결과값에 따른 처리사항 | |
변경 전AutoSendConfigController.php
| { | |
| public function index() | |
| { | |
| $code = Request::get()->get('code'); | |
| $isBlock = false; | |
| $blockMode = null; | |
변경 후AutoSendConfigController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $code = Request::get()->get('code'); | |
| $isBlock = false; | |
| $blockMode = null; | |
변경 전AutoSendController.php
| { | |
| public function index() | |
| { | |
| $request = Request::get()->toArray(); | |
| $this->callMenu('crm', 'messageSend', 'autoSend'); | |
변경 후AutoSendController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $request = Request::get()->toArray(); | |
| $this->callMenu('crm', 'messageSend', 'autoSend'); | |
변경 전CrmRecipeSendController.php
| public function index() | |
| { | |
| $this->callMenu('crm', 'crm', 'crmRecipe'); | |
| $this->setMenuCode('crm', 'crm', 'crmRecipe'); | |
변경 후CrmRecipeSendController.php
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'crm', 'crmRecipe'); | |
| $this->setMenuCode('crm', 'crm', 'crmRecipe'); | |
변경 전IndexController.php
| { | |
| public function index() | |
| { | |
| $this->redirect('./crm_group.php'); | |
| } | |
| } | |
변경 후IndexController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->redirect('./crm_group.php'); | |
| } | |
| } | |
변경 전MailGateBridgeController.php
| { | |
| public function index() | |
| { | |
| $pMail = \App::load('\\Component\\Mail\\Pmail'); | |
| $pMail->setPmail(); | |
변경 후MailGateBridgeController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $pMail = \App::load('\\Component\\Mail\\Pmail'); | |
| $pMail->setPmail(); | |
변경 전MailGateController.php
| { | |
| public function index() | |
| { | |
| // --- 모듈 호출 | |
| $data = null; | |
변경 후MailGateController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| // --- 모듈 호출 | |
| $data = null; | |
변경 전MailSendController.php
| */ | |
| public function index() | |
| { | |
| /** | |
| * 네비게이션 설정 | |
| */ | |
변경 후MailSendController.php
| */ | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| /** | |
| * 네비게이션 설정 | |
| */ | |
변경 전MailSendReceiveRefuseCountController.php
| */ | |
| public function index() | |
| { | |
| /** | |
| * @var \Bundle\Component\Member\MemberAdmin $memberAdmin | |
| */ | |
변경 후MailSendReceiveRefuseCountController.php
| */ | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| /** | |
| * @var \Bundle\Component\Member\MemberAdmin $memberAdmin | |
| */ | |
변경 전MessageConfigController.php
| public function index() | |
| { | |
| // 메뉴 설정 | |
| $this->callMenu('crm', 'messageConfig', 'messageConfig'); | |
| $this->setMenuCode('crm', 'messageConfig', 'messageConfig'); | |
변경 후MessageConfigController.php
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| // 메뉴 설정 | |
| $this->callMenu('crm', 'messageConfig', 'messageConfig'); | |
| $this->setMenuCode('crm', 'messageConfig', 'messageConfig'); | |
변경 전MessageTemplateController.php
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageSend', 'messageTemplate'); | |
| $this->getView()->setPageName('crm/message_template.php'); | |
| $this->getView()->setDefine('messageTemplateSearch', 'crm/message_template/message_template_search.php'); | |
변경 후MessageTemplateController.php
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageSend', 'messageTemplate'); | |
| $this->getView()->setPageName('crm/message_template.php'); | |
| $this->getView()->setDefine('messageTemplateSearch', 'crm/message_template/message_template_search.php'); | |
변경 전MessageTemplateRegisterController.php
| public function index() | |
| { | |
| $request = \App::getInstance('request'); | |
| $requestData = $request->request()->toArray(); | |
변경 후MessageTemplateRegisterController.php
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $request = \App::getInstance('request'); | |
| $requestData = $request->request()->toArray(); | |
변경 전MobileHistoryController.php
| { | |
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageHistory', 'mobileHistory'); | |
| $this->setMenuCode('crm', 'messageHistory', 'mobileHistory'); | |
변경 후MobileHistoryController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageHistory', 'mobileHistory'); | |
| $this->setMenuCode('crm', 'messageHistory', 'mobileHistory'); | |
변경 전MobileHistoryListController.php
| { | |
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageHistory', 'mobileHistoryList'); | |
| /** @var Request $request */ | |
변경 후MobileHistoryListController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageHistory', 'mobileHistoryList'); | |
| /** @var Request $request */ | |
변경 전MobileSendController.php
| { | |
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageSend', 'mobileSend'); | |
| // 현재 SMS 포인트 싱크 | |
변경 후MobileSendController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageSend', 'mobileSend'); | |
| // 현재 SMS 포인트 싱크 | |
변경 전PopupChargeMessagePointsController.php
| { | |
| public function index() | |
| { | |
| $request = \App::getInstance('request'); | |
| $session = \App::getInstance('session'); | |
| $globals = \App::getInstance('globals'); | |
변경 후PopupChargeMessagePointsController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $request = \App::getInstance('request'); | |
| $session = \App::getInstance('session'); | |
| $globals = \App::getInstance('globals'); | |
변경 전PopupManageCallNumberController.php
| { | |
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageConfig', 'manageCallNumber'); | |
| $this->setMenuCode('crm', 'messageConfig', 'manageCallNumber'); | |
변경 후PopupManageCallNumberController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageConfig', 'manageCallNumber'); | |
| $this->setMenuCode('crm', 'messageConfig', 'manageCallNumber'); | |
변경 전PopupSelectMembersController.php
| { | |
| public function index() | |
| { | |
| $this->callMenu('crm', 'messageSend', 'mobileSend'); | |
| /** @var Request $request */ | |
변경 후PopupSelectMembersController.php
| { | |
| public function index() | |
| { | |
| $this->setNcdsSubBodyClass(); | |
| $this->callMenu('crm', 'messageSend', 'mobileSend'); | |
| /** @var Request $request */ | |
변경 전regular_order.html
| } | |
| }); | |
| } | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| <!--{ / }--> | |
| </script> | |
| { # footer } | |
변경 후regular_order.html
| } | |
| }); | |
| } | |
| <!--{ / }--> | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| </script> | |
| { # footer } | |
변경 전regular_order.html
| } | |
| }); | |
| } | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| <!--{ / }--> | |
| </script> | |
| { # footer } | |
변경 후regular_order.html
| } | |
| }); | |
| } | |
| <!--{ / }--> | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| </script> | |
| { # footer } | |
변경 전regular_order.html
| } | |
| }); | |
| } | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| <!--{ / }--> | |
| </script> | |
| { # footer } | |
변경 후regular_order.html
| } | |
| }); | |
| } | |
| <!--{ / }--> | |
| // 동적으로 카드 라디오버튼을 추가 | |
| function showCardInfo(cardName, cardNo, encryptCardNo) { | |
| showCardInfo(cardName, cardMaskNo, encryptCardNo); | |
| document.getElementById("cardRegistLayer").remove(); | |
| } | |
| </script> | |
| { # footer } | |
변경 전goods_register_option_stock.php
| $imageInput = '<input type="hidden" name="imageDB[sno][]" value="' . $iVal['sno'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageSize][]" value="' . $iVal['imageSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageNo][]" value="' . $iVal['imageNo'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageKind][]" value="' . $iVal['imageKind'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageName][]" value="' . $iVal['imageName'] . '" /> '; | |
변경 후goods_register_option_stock.php
| $imageInput = '<input type="hidden" name="imageDB[sno][]" value="' . $iVal['sno'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageSize][]" value="' . $iVal['imageSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageHeightSize][]" value="' . $iVal['imageHeightSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageNo][]" value="' . $iVal['imageNo'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageKind][]" value="' . $iVal['imageKind'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageName][]" value="' . $iVal['imageName'] . '" /> '; | |
변경 전goods_register.php
| $imageInput = '<input type="hidden" name="imageDB[sno][]" value="' . $iVal['sno'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageSize][]" value="' . $iVal['imageSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageNo][]" value="' . $iVal['imageNo'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageKind][]" value="' . $iVal['imageKind'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageName][]" value="' . $iVal['imageName'] . '" /> '; | |
변경 후goods_register.php
| $imageInput = '<input type="hidden" name="imageDB[sno][]" value="' . $iVal['sno'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageSize][]" value="' . $iVal['imageSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageHeightSize][]" value="' . $iVal['imageHeightSize'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageNo][]" value="' . $iVal['imageNo'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageKind][]" value="' . $iVal['imageKind'] . '" /> '; | |
| $imageInput .= '<input type="hidden" name="imageDB[imageName][]" value="' . $iVal['imageName'] . '" /> '; | |
변경 전Goods.php
| $this->search['reSearchKey'] = gd_isset(gd_array_values($getValue['reSearchKey'])); | |
| $this->search['reSearch'] = gd_isset($getValue['reSearch']); | |
| $this->search['cateGoods'] = ArrayUtils::last(gd_isset($getValue['cateGoods'])); | |
| $this->search['brand'] = gd_isset($getValue['brand']); | |
| $this->search['quickBrandGoods'] = gd_isset($getValue['quickBrandGoods']); | |
변경 후Goods.php
| $this->search['reSearchKey'] = gd_isset(gd_array_values($getValue['reSearchKey'])); | |
| $this->search['reSearch'] = gd_isset($getValue['reSearch']); | |
| // 검색 필드키 화이트리스트 검증 (SQL 식별자 인젝션 방어 - 허용된 검색키만 컬럼명으로 결합) | |
| $allowedSearchKey = array_merge(array_keys($this->search['combineSearch']), ['brandNm']); | |
| if ($this->search['key'] && !in_array($this->search['key'], $allowedSearchKey, true)) { | |
| $this->search['key'] = 'all'; | |
| } | |
| if (is_array($this->search['reSearchKey'])) { | |
| foreach ($this->search['reSearchKey'] as $reSearchKeyIdx => $reSearchKeyVal) { | |
| if (!in_array($reSearchKeyVal, $allowedSearchKey, true)) { | |
| unset($this->search['reSearchKey'][$reSearchKeyIdx]); | |
| unset($this->search['reSearchKeyword'][$reSearchKeyIdx]); | |
| } | |
| } | |
| } | |
| $this->search['cateGoods'] = ArrayUtils::last(gd_isset($getValue['cateGoods'])); | |
| $this->search['brand'] = gd_isset($getValue['brand']); | |
| $this->search['quickBrandGoods'] = gd_isset($getValue['quickBrandGoods']); | |
변경 전MyPage.php
| } | |
| // 사업자번호 중복여부 체크 | |
| if ($requestParams['memberFl'] == 'business' && ($require['busiNo'] || !empty($requestParams['busiNo']))) { | |
| $newBusiNo = gd_remove_special_char($requestParams['busiNo']); | |
| $memberData = $this->myInformation(); | |
| $oldBusiNo = $memberData['busiNo']; | |
변경 후MyPage.php
| } | |
| // 사업자번호 중복여부 체크 | |
| if (!empty($joinItemPolicy['businessinfo']) && $requestParams['memberFl'] == 'business' && ($require['busiNo'] || !empty($requestParams['busiNo']))) { | |
| $newBusiNo = gd_remove_special_char($requestParams['busiNo']); | |
| $memberData = $this->myInformation(); | |
| $oldBusiNo = $memberData['busiNo']; | |
변경 전MyPagePsController.php
| $requestParams = array_merge($request->post()->xss()->all(), $request->files()->toArray()); | |
| // CSRF 토큰 체크 | |
| if (!Token::check('myPageToken', $requestParams)) { | |
| throw new Exception(__('잘못된 경로로 접근하셨습니다.')); | |
| } | |
변경 후MyPagePsController.php
| $requestParams = array_merge($request->post()->xss()->all(), $request->files()->toArray()); | |
| // CSRF 토큰 체크 | |
| // 숨김 iframe 으로 제출되어 검증 실패 시 폼이 다시 그려지지 않으므로, 토큰을 소거하지 않고 재제출을 허용한다. | |
| if (!Token::check('myPageToken', $requestParams, false, null, true)) { | |
| throw new Exception(__('잘못된 경로로 접근하셨습니다.')); | |
| } | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('js_btn_join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('js_btn_join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('js_btn_join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('js_btn_join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('btn-join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('btn-join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('join_ok_btn')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('join_ok_btn')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('join_ok_btn')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('join_ok_btn')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전gd_member2.js
| var $button = $(parent.document.getElementsByClassName('btn-join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 후gd_member2.js
| var $button = $(parent.document.getElementsByClassName('btn-join')[0]); | |
| $button.html('<em>' + $button.val() + '</em>'); | |
| $button.data('action', ''); | |
| // validation_submit 에서 잠근 버튼을 함께 풀어야 검증 실패 후 재제출이 가능하다 | |
| $button.prop('disabled', false); | |
| }); | |
| $this.data('action', 'click'); | |
| $this.html('<em>' + __('진행 중') + '</em>'); | |
변경 전kakao_login_config.php
| * @var array $checked 카카오 로그인 설정 여부 'checked="checked"' | |
| * @var array $data KakaoLoginPolicy 설정 정보 | |
| * @var bool $installedKakaoSync 카카오 싱크 앱 설치 여부 | |
| * @var bool $useKakaoSync 카카오 싱크 사용 여부 | |
| * @var bool $useKakaoLogin 카카오 로그인 사용 여부 | |
| * @var bool $isAvailableOnlyKakaoSync 카카오 싱크 배포일 이후 상점 true, 이전 상점 false | |
| ?> | |
| <link type="text/css" href="<?= PATH_ADMIN_GD_SHARE ?>script/slider/slick/slick.css" rel="stylesheet"/> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/slider/slick/slick.js"></script> | |
| <?php if ($installedKakaoSync && $isAvailableOnlyKakaoSync === false) : ?> | |
| <div class="page-header js-affix"> | |
| <h3><?php echo end($naviMenu->location); ?></h3> | |
| </div> | |
변경 후kakao_login_config.php
| * @var array $checked 카카오 로그인 설정 여부 'checked="checked"' | |
| * @var array $data KakaoLoginPolicy 설정 정보 | |
| * @var bool $installedKakaoSync 카카오 싱크 앱 설치 여부 | |
| * @var bool $installedKakaoLogin 카카오 로그인 설치 여부 | |
| * @var bool $useKakaoSync 카카오 싱크 사용 여부 | |
| * @var bool $useKakaoLogin 카카오 로그인 사용 여부 | |
| * @var bool $isAvailableOnlyKakaoSync 카카오 싱크 배포일 이후 상점 true, 이전 상점 false | |
| ?> | |
| <link type="text/css" href="<?= PATH_ADMIN_GD_SHARE ?>script/slider/slick/slick.css" rel="stylesheet"/> | |
| <script type="text/javascript" src="<?= PATH_ADMIN_GD_SHARE ?>script/slider/slick/slick.js"></script> | |
| <?php if ($installedKakaoSync || !$installedKakaoLogin) : ?> | |
| <div class="page-header js-affix"> | |
| <h3><?php echo end($naviMenu->location); ?></h3> | |
| </div> | |
변경 전KakaoLoginConfigController.php
| $kakaoLoginPolicy = \App::getInstance(KakaoLoginPolicy::class); | |
| $policy = $kakaoLoginPolicy->getPolicy(); | |
| gd_isset($policy['useFl'], 'n'); | |
| gd_isset($policy['simpleLoginFl'],'y'); | |
| gd_isset($policy['baseInfo'],'y'); | |
| $this->setData('checked', $checked); | |
| $this->setData('data', $policy); | |
| $this->setData('installedKakaoSync', $kakaoLoginPolicy->installedKakaoSync()); | |
| $this->setData('useKakaoSync', $kakaoLoginPolicy->useKakaoSync()); | |
| $this->setData('useKakaoLogin', $kakaoLoginPolicy->useKakaoLogin()); | |
| $this->setData('isAvailableOnlyKakaoSync', $isAvailableOnlyKakaoSync); | |
변경 후KakaoLoginConfigController.php
| $kakaoLoginPolicy = \App::getInstance(KakaoLoginPolicy::class); | |
| $policy = $kakaoLoginPolicy->getPolicy(); | |
| //카카오싱크 미설치 상태에서 Policy가 비어있지 않으면, 카카오 로그인 세팅된 것으로 간주 | |
| $isInstalledKakaoLogin = !$kakaoLoginPolicy->installedKakaoSync() && !empty($policy); | |
| gd_isset($policy['useFl'], 'n'); | |
| gd_isset($policy['simpleLoginFl'],'y'); | |
| gd_isset($policy['baseInfo'],'y'); | |
| $this->setData('checked', $checked); | |
| $this->setData('data', $policy); | |
| $this->setData('installedKakaoSync', $kakaoLoginPolicy->installedKakaoSync()); | |
| $this->setData('installedKakaoLogin', $isInstalledKakaoLogin); | |
| $this->setData('useKakaoSync', $kakaoLoginPolicy->useKakaoSync()); | |
| $this->setData('useKakaoLogin', $kakaoLoginPolicy->useKakaoLogin()); | |
| $this->setData('isAvailableOnlyKakaoSync', $isAvailableOnlyKakaoSync); | |
변경 전OrderEndController.php
| use Bundle\Service\Order\OrderEndService; | |
| use Component\CartRemind\CartRemind; | |
| use Component\Mall\Mall; | |
| use Message; | |
| use Session; | |
| use Request; | |
| } | |
| } | |
| //facebook Dynamic Ads 외부 스크립트 적용 | |
| $facebookAd = \App::Load('\\Component\\Marketing\\FacebookAd'); | |
| $currency = gd_isset(Mall::getSession('currencyConfig')['code'], 'KRW'); | |
| $fbConfig = $facebookAd->getConfig(); | |
| $fbConfigExtension = $facebookAd->getExtensionConfig(); | |
| if(($fbConfig['fbUseFl'] == 'y' && $fbConfig['orderEndScriptFl'] == 'y') || $fbConfigExtension['fbUseFl'] == 'y') { | |
| $goodsInfo = $order->getOrderGoodsData($orderInfo['orderNo']); | |
| // 상품번호 추출 | |
| $goodsNo = []; | |
| $goodsNo[] = $val2['goodsNo']; | |
| } | |
| } | |
| $fbScript = $facebookAd->getFbOrderEndScript($goodsNo, $orderInfo['settlePrice'], $currency); | |
| $this->setData('fbOrderEndScript', $fbScript['script']); | |
변경 후OrderEndController.php
| use Bundle\Service\Order\OrderEndService; | |
| use Component\CartRemind\CartRemind; | |
| use Component\Mall\Mall; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Message; | |
| use Session; | |
| use Request; | |
| } | |
| } | |
| //facebook Dynamic Ads 외부 스크립트 적용(결제가 정상적으로 이루어지지 않은경우 제외 출력) | |
| $facebookAd = \App::Load('\\Component\\Marketing\\FacebookAd'); | |
| $currency = gd_isset(Mall::getSession('currencyConfig')['code'], 'KRW'); | |
| $fbConfig = $facebookAd->getConfig(); | |
| $fbConfigExtension = $facebookAd->getExtensionConfig(); | |
| if($orderInfo['orderStatus'] != OrderStatusGroup::FAIL->value && (($fbConfig['fbUseFl'] == 'y' && $fbConfig['orderEndScriptFl'] == 'y') || $fbConfigExtension['fbUseFl'] == 'y')) { | |
| $goodsInfo = $order->getOrderGoodsData($orderInfo['orderNo']); | |
| // 상품번호 추출 | |
| $goodsNo = []; | |
| $goodsNo[] = $val2['goodsNo']; | |
| } | |
| } | |
| $facebookAd->orderNo = $orderInfo['orderNo']; | |
| $fbScript = $facebookAd->getFbOrderEndScript($goodsNo, $orderInfo['settlePrice'], $currency); | |
| $this->setData('fbOrderEndScript', $fbScript['script']); | |
변경 전OrderEndController.php
| use Component\Mall\Mall; | |
| use DateTime; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Message; | |
| use Session; | |
| use Request; | |
| } | |
| } | |
| //facebook Dynamic Ads 외부 스크립트 적용 | |
| $facebookAd = \App::Load('\\Component\\Marketing\\FacebookAd'); | |
| $currency = gd_isset(Mall::getSession('currencyConfig')['code'], 'KRW'); | |
| $fbConfig = $facebookAd->getConfig(); | |
| $fbConfigExtension = $facebookAd->getExtensionConfig(); | |
| $goodsInfo = $order->getOrderGoodsData($orderInfo['orderNo']); | |
| if(($fbConfig['fbUseFl'] == 'y' && $fbConfig['orderEndScriptFl'] == 'y') || $fbConfigExtension['fbUseFl'] == 'y') { | |
| // 상품번호 추출 | |
| $goodsNo = []; | |
| foreach ($goodsInfo as $key => $val){ | |
| $goodsNo[] = $val2['goodsNo']; | |
| } | |
| } | |
| $fbScript = $facebookAd->getFbOrderEndScript($goodsNo, $orderInfo['settlePrice'], $currency); | |
| $this->setData('fbOrderEndScript', $fbScript['script']); | |
변경 후OrderEndController.php
| use Component\Mall\Mall; | |
| use DateTime; | |
| use Framework\Debug\Exception\AlertRedirectException; | |
| use Origin\Enum\Order\OrderStatusGroup; | |
| use Message; | |
| use Session; | |
| use Request; | |
| } | |
| } | |
| //facebook Dynamic Ads 외부 스크립트 적용(결제가 정상적으로 이루어지지 않은경우 제외 출력) | |
| $facebookAd = \App::Load('\\Component\\Marketing\\FacebookAd'); | |
| $currency = gd_isset(Mall::getSession('currencyConfig')['code'], 'KRW'); | |
| $fbConfig = $facebookAd->getConfig(); | |
| $fbConfigExtension = $facebookAd->getExtensionConfig(); | |
| $goodsInfo = $order->getOrderGoodsData($orderInfo['orderNo']); | |
| if($orderInfo['orderStatus'] != OrderStatusGroup::FAIL->value && (($fbConfig['fbUseFl'] == 'y' && $fbConfig['orderEndScriptFl'] == 'y') || $fbConfigExtension['fbUseFl'] == 'y')) { | |
| // 상품번호 추출 | |
| $goodsNo = []; | |
| foreach ($goodsInfo as $key => $val){ | |
| $goodsNo[] = $val2['goodsNo']; | |
| } | |
| } | |
| $facebookAd->orderNo = $orderInfo['orderNo']; | |
| $fbScript = $facebookAd->getFbOrderEndScript($goodsNo, $orderInfo['settlePrice'], $currency); | |
| $this->setData('fbOrderEndScript', $fbScript['script']); | |
변경 전MemberSnsDAO.php
| $this->db->strField .= ', m.email, m.adultConfirmDt, m.adultFl, m.loginCnt, m.changePasswordDt, m.guidePasswordDt'; | |
| $this->db->strField .= ', m.modDt AS mModDt, m.regDt AS mRegDt, ms.snsJoinFl, ms.snsTypeFl, ms.connectFl, ms.accessToken'; | |
| $this->db->strField .= ', mg.groupNm, mg.groupSort, mh.sno AS hackOutSno'; | |
| $this->db->strJoin = ' LEFT JOIN ' . DB_MEMBER . ' AS m ON ms.memNo = m.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_GROUP . ' AS mg ON mg.sno = m.groupSno'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HACKOUT . ' AS mh ON mh.memNo = m.memNo'; | |
변경 후MemberSnsDAO.php
| $this->db->strField .= ', m.email, m.adultConfirmDt, m.adultFl, m.loginCnt, m.changePasswordDt, m.guidePasswordDt'; | |
| $this->db->strField .= ', m.modDt AS mModDt, m.regDt AS mRegDt, ms.snsJoinFl, ms.snsTypeFl, ms.connectFl, ms.accessToken'; | |
| $this->db->strField .= ', mg.groupNm, mg.groupSort, mh.sno AS hackOutSno'; | |
| $this->db->strField .= ', m.mallSno'; // 세션 저장 시 기준몰 판정에 사용 (누락되면 세션 핸들러가 회원을 재조회하며 세션ID를 재발급한다) | |
| $this->db->strJoin = ' LEFT JOIN ' . DB_MEMBER . ' AS m ON ms.memNo = m.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_GROUP . ' AS mg ON mg.sno = m.groupSno'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . DB_MEMBER_HACKOUT . ' AS mh ON mh.memNo = m.memNo'; | |
변경 전layer_preview_mobile_send.php
| <script> | |
| function resolveReplaceCodeForPreview(content, isMain = true) { | |
| return MobileMessageReplaceCode.resolvePreviewContent(content, { | |
| shortLinkKeys: isMain ? window.shortLinkKeys : window.shortLinkAlternativeKeys, | |
| }); | |
| } | |
변경 후layer_preview_mobile_send.php
| <script> | |
| function resolveReplaceCodeForPreview(content, isMain = true) { | |
| return MobileMessageReplaceCode.resolvePreviewContent(content, { | |
| includeExcelUpload: isExcelUploadSmsContext(), | |
| shortLinkKeys: isMain ? window.shortLinkKeys : window.shortLinkAlternativeKeys, | |
| }); | |
| } | |
변경 전layer_send_method_setting.php
| return MobileMessageReplaceCode.resolvePreviewContent(content, { | |
| includeRecipe: true, | |
| shortLinkKeys: isMain ? window.shortLinkKeys : window.shortLinkAlternativeKeys, | |
| }); | |
| } | |
변경 후layer_send_method_setting.php
| return MobileMessageReplaceCode.resolvePreviewContent(content, { | |
| includeRecipe: true, | |
| includeExcelUpload: isExcelUploadSmsContext(), | |
| shortLinkKeys: isMain ? window.shortLinkKeys : window.shortLinkAlternativeKeys, | |
| }); | |
| } | |
변경 전ExcelSms.php
| 'text' => '이름', | |
| 'comment' => '', | |
| 'sample' => '홍길동', | |
| 'desc' => '불필요한 경우 이름 필드 열을 삭제하여 주시기 바랍니다.<br/>(삭제하지 않고 공란으로 입력 시 해당 번호는 업로드할 수 없음)<br/>- 치환코드 {name}으로 발송 내용에 이름 입력 가능', | |
| ], | |
| [ | |
| 'dbKey' => 'cellPhone', | |
변경 후ExcelSms.php
| 'text' => '이름', | |
| 'comment' => '', | |
| 'sample' => '홍길동', | |
| 'desc' => '불필요한 경우 이름 필드 열을 삭제하여 주시기 바랍니다.<br/>(삭제하지 않고 공란으로 입력 시 해당 번호는 업로드할 수 없음)<br/>- 치환코드 {name}으로 발송 내용에 이름 입력 가능<br/>※단, SMS/LMS 전용이며 친구톡에서는 치환되지 않고 문자열 그대로 표시됩니다.', | |
| ], | |
| [ | |
| 'dbKey' => 'cellPhone', | |
변경 전CouponAdmin.php
| } | |
| $arrData = []; | |
| $arrData['couponNo'] = $getValue['couponNo']; | |
| $arrData['couponSaveAdminId'] = Session::get('manager.managerId'); | |
| $arrData['managerNo'] = Session::get('manager.sno'); | |
| $arrData['memberCouponStartDate'] = $this->getMemberCouponStartDate($getValue['couponNo']); | |
| $arrData['memberCouponEndDate'] = $this->getMemberCouponEndDate($getValue['couponNo']); | |
| // 저장 | |
| $arrBind = $this->db->get_binding(DBTableField::tableMemberCoupon(), $arrData, 'insert', gd_array_keys($arrData), ['memberCouponNo']); | |
| $this->db->set_insert_db(DB_MEMBER_COUPON, $arrBind['param'], $arrBind['bind'], 'y'); | |
| $this->setCouponMemberSaveCount($getValue['couponNo']); | |
| } | |
| return 'T'; | |
| exit; | |
| } | |
변경 후CouponAdmin.php
| } | |
| $arrData = []; | |
| $arrData['couponNo'] = $getValue['couponNo']; | |
| $arrData['couponSaveAdminId'] = gd_isset(Request::post()->get('couponSaveAdminId'), Session::get('manager.managerId')); | |
| $arrData['managerNo'] = Session::get('manager.sno'); | |
| $arrData['memberCouponStartDate'] = $this->getMemberCouponStartDate($getValue['couponNo']); | |
| $arrData['memberCouponEndDate'] = $this->getMemberCouponEndDate($getValue['couponNo']); | |
| // 저장 | |
| $arrBind = $this->db->get_binding(DBTableField::tableMemberCoupon(), $arrData, 'insert', gd_array_keys($arrData), ['memberCouponNo']); | |
| $this->db->set_insert_db(DB_MEMBER_COUPON, $arrBind['param'], $arrBind['bind'], 'y'); | |
| } | |
| // 발급 카운트 일괄 증가 (루프 내 N회 UPDATE → 1회 UPDATE) | |
| $this->setCouponMemberSaveCountAll($getValue['couponNo'], count($memNoArr)); | |
| return 'T'; | |
| exit; | |
| } | |
변경 전MemberTableField.php
| 'typ' => 's', | |
| 'def' => null, | |
| ]; // 평생회원 전환일 | |
| return $arrField; | |
| } | |
변경 후MemberTableField.php
| 'typ' => 's', | |
| 'def' => null, | |
| ]; // 평생회원 전환일 | |
| $arrField[] = [ | |
| 'val' => 'autoGroupAppraisalDt', | |
| 'typ' => 's', | |
| 'def' => null, | |
| ]; // 회원등급평가 실행일 | |
| return $arrField; | |
| } | |
변경 전AppraisalMailSender.php
| use Component\Mail\MailUtil; | |
| use Component\Validator\Validator; | |
| /** | |
| public function send() | |
| { | |
| foreach ($this->receiver as $index => $item) { | |
| $groupVo = new \Component\Member\Group\GroupDomain($item[1]); | |
| if (!($groupVo instanceof GroupDomain)) { | |
| \App::getInstance('logger')->error('그룹정보 객체 오류', $item); | |
| continue; | |
| } | |
| MailUtil::sendMemberGroupChangeMail($item[0], $groupVo); | |
| } | |
| } | |
변경 후AppraisalMailSender.php
| use Component\Mail\MailUtil; | |
| use Component\Member\Group\GroupDomain; | |
| use Component\Validator\Validator; | |
| /** | |
| public function send() | |
| { | |
| // 같은 등급 GroupDomain을 재사용해 setGroupDcData()의 회원 수만큼 반복 DB조회(N+1)를 제거한다. | |
| $groupVoCache = []; | |
| foreach ($this->receiver as $index => $item) { | |
| $groupSno = isset($item[1]['sno']) ? $item[1]['sno'] : null; | |
| if ($groupSno !== null && isset($groupVoCache[$groupSno])) { | |
| $groupVo = $groupVoCache[$groupSno]; | |
| } else { | |
| $groupVo = new GroupDomain($item[1]); | |
| if (!($groupVo instanceof GroupDomain)) { | |
| \App::getInstance('logger')->error('그룹정보 객체 오류', $item); | |
| continue; | |
| } | |
| if ($groupSno !== null) { | |
| $groupVoCache[$groupSno] = $groupVo; | |
| } | |
| } | |
| MailUtil::sendMemberGroupChangeMail($item[0], $groupVo); | |
| } | |
| } | |
변경 전Appraisal.php
| namespace Bundle\Component\Member\Group; | |
| use App; | |
| use Component\Database\DBTableField; | |
| use Component\Member\Member; | |
| use Component\Sms\Code; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Session; | |
| /** | |
| protected $search; | |
| /** @var AppraisalMailSender 등급평가 메일발송 */ | |
| protected $mailSender; | |
| /** @var array 등급평가 완료된 회원번호 */ | |
| protected $completeMemNo = []; | |
| /** @var string 등급평가일시 */ | |
| protected $appraisalDateTime; | |
| /** @var bool 현재 평가 등급 기준치 만족 여부 */ | |
| /** @var array 현재 평가대상 회원 */ | |
| protected $currentMembers; | |
| /** @var array 등급평가 제외 설정된 등급 sno 배열 */ | |
| protected $apprExclusionOfRating; | |
| /** @var array 그룹 sno별 등급 */ | |
| protected $groupSort; | |
| /** @var array 그룹 관리 설정 */ | |
| public $policy; | |
| /** @var array 기본 설정 */ | |
| public $basicInfo; | |
| /** | |
| * Appraisal constructor. | |
| * | |
| public function __construct(AppraisalSearch $search = null) | |
| { | |
| parent::__construct(); | |
| $this->setSearch($search); | |
| $this->groupConfig(); | |
| $this->validateAppraisalGroupConfig(); | |
| $this->policy = ComponentUtils::getPolicy('member.group'); | |
| $this->basicInfo = gd_policy('basic.info'); | |
| ini_set('memory_limit', '-1'); | |
| } | |
| } | |
| if ($data['apprSystem'] == 'point' && $data['appraisalPointOrderPriceFl'] != 'y' && $data['appraisalPointOrderRepeatFl'] != 'y' && $data['appraisalPointReviewRepeatFl'] != 'y' && $data['appraisalPointLoginRepeatFl'] != 'y') { | |
| $logger = \App::getInstance('logger'); | |
| $logger->warning('Not set appraisal performance point'); | |
| throw new Exception(__('실적 점수제 평가 설정 값이 없습니다.')); | |
| } | |
| $this->appraisalGroupConfig = new SimpleStorage($data); | |
| $validation->validateOverlapStandard(); | |
| $this->groupSort[$group['sno']] = $group['groupSort']; // 그룹 key: sno, value: sort 배열 생성 | |
| } | |
| // 회원등급 평가시 제외인 등급 그룹 배열 생성 | |
| $exclusionGroups = $dao->selectGroupExclusion(); | |
| foreach ($exclusionGroups as $key){ | |
| $this->groupConfig = $groups; | |
| } | |
| /** | |
| * setGroupNames | |
| * @return void | |
| */ | |
| public function appraisalGroupBySearch() | |
| { | |
| $logger = \App::getInstance('logger'); | |
| $logger->notice('Start group appraisal.'); | |
| $total = $this->countTotalMember(); | |
| $limit = $this->search->getAppraisalLimit(); | |
| $this->countByTotalMember = $this->appraisalCountByTotalMember($total, $limit); | |
| $logger->notice('총 회원[' . $total . '], 1회 평가당 제한 인원수[' . $limit . '], 평가 실행 횟수[' . $this->countByTotalMember . ']'); | |
| $this->completeMemNo = []; | |
| $this->appraisalDateTime = DateTimeUtils::dateFormat('Y-m-d H:i:s', 'now'); | |
| for ($offset = 0; $offset < $this->countByTotalMember; $offset++) { | |
| $this->appraisalGroupByOffset($offset); | |
| // 평가 대상으로 검색된 회원 초기화 | |
| $this->currentMembers = null; | |
| } | |
| $logger->notice('End group appraisal.'); | |
| } | |
| /** | |
| */ | |
| public function appraisalGroupByOffset($offset) | |
| { | |
| $logger = \App::getInstance('logger'); | |
| $db = \App::getInstance('DB'); | |
| $this->search->setAppraisalOffset($offset); | |
| $logger->info(sprintf('Start appraisal group set offset %s', $offset)); | |
| foreach ($this->groupConfig as $index => $item) { | |
| $db->ping(); | |
| $logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| $this->group = new SimpleStorage($item); | |
| if ($this->currentMembers === null) { | |
| $this->currentMembers = $this->search->search($this->group); | |
| } | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $logger->info(sprintf('has appraisal member count is %d', gd_count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } | |
| $logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| } | |
| if ($this->policy['downwardAdjustment'] == 'y') { | |
| $this->isDefaultGroupMember = true; | |
| $logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| $this->group = new SimpleStorage($this->defaultGroupConfig); | |
| $this->search->setAppraisalDateTime($this->appraisalDateTime); | |
| $this->currentMembers = $this->search->searchDefaultGroup($this->appraisalDateTime); | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $db->ping(); | |
| $logger->info(sprintf('has appraisal member count is %d', gd_count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } else { | |
| $logger->info('Not found appraisal members by default group', $this->defaultGroupConfig); | |
| } | |
| } | |
| $logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| $this->isDefaultGroupMember = false; | |
| } | |
| /** | |
| * appraisalMailSend | |
| * @return void | |
| */ | |
| public function updateGroupWithAddMailReceiver(array $members) | |
| { | |
| $logger = \App::getInstance('logger'); | |
| $session = \App::getInstance('session'); | |
| $db = \App::getInstance('DB'); | |
| try { | |
| $groupSno = $this->group->get('sno'); | |
| $settleGb = $this->group->get('settleGb'); | |
| $smsSender = \App::load(\Component\Sms\SmsSender::class); | |
| $smsSender->validPassword(\Request::post()->get('password')); | |
| } | |
| $count = 500; | |
| foreach ($members as $index => $item) { | |
| $count--; | |
| if ($count == 0) { | |
| $db->ping(); | |
| $count = 500; | |
| } | |
| $session->set(Member::SESSION_MODIFY_MEMBER_INFO, $item); | |
| $storage = new SimpleStorage($item); | |
| $storage->set('settleGb', $settleGb); | |
| $memNo = $storage->get('memNo'); | |
| array_push($this->completeMemNo, $memNo); | |
| // 현재 등급이 '등급평가시 제외' 설정이 아닐 때 | |
| if(gd_array_key_exists($item['groupSno'], $this->apprExclusionOfRating) == false) { | |
| $this->checkGroupByAppraisalSystem($item); | |
| $beforeGroupSort = $this->groupSort[$item['groupSno']]; | |
| $afterGroupSort = $this->groupSort[$groupSno]; | |
| //하향펑가를 설정하지 않았거나, 하향평가를 사용하거나, 하향평가를 사용하지 않고 변경 등급이 기존 등급보다 높거나 같을 때 만 업데이트 | |
| if (empty($this->policy['downwardAdjustment']) || $this->policy['downwardAdjustment'] == 'y' || ($this->policy['downwardAdjustment'] == 'n' && $beforeGroupSort < $afterGroupSort)) { | |
| if ($this->isCurrentGroupMember || $this->isDefaultGroupMember) { | |
| $logger->info('Group change target. sno[' . $this->group->get('sno', 0) . '], name[' . $this->group->get('', '-') . ']', $item); | |
| $this->updateGroup($memNo); | |
| $this->writeHistory($memNo); | |
| $this->addMailReceiver($storage, $this->group); | |
| $this->addSmsReceiver($storage, $this->group); | |
| unset($members[$index]); | |
| } | |
| } | |
| } | |
| } | |
| if ($this->isTran) { | |
| $db->commit(); | |
| $this->currentMembers = $members; | |
| } | |
| } catch (Exception $e) { | |
| $logger->error(__METHOD__ . ', ' . $e->getFile() . '[' . $e->getLine() . '], ' . $e->getMessage(), $e->getTrace()); | |
| $db->rollback(); | |
| } | |
| } | |
| /** | |
| * checkGroupByAppraisalSystem | |
| * | |
| * @param array $item 등급평가 대상의 기준치 정보 | |
| * | |
| } | |
| } | |
| if ($point > 0) { | |
| $logger = \App::getInstance('logger'); | |
| $logger->info( | |
| __METHOD__, [ | |
| 'memNo:'.$memNo, | |
| $point, | |
| */ | |
| public function checkGroupByFigure($item) | |
| { | |
| $logger = \App::getInstance('logger'); | |
| $this->isCurrentGroupMember = true; | |
| $priceUnit = 10000; | |
| */ | |
| public function updateGroupWithInsertHistory(SimpleStorage $storage) | |
| { | |
| $memNo = $storage->get('memNo'); | |
| $this->updateGroup($memNo); | |
| $this->writeHistory($memNo); | |
| } | |
| /** | |
| } | |
| } | |
| $passwordCheckFl = gd_isset(\Request::post()->get('passwordCheckFl'), 'y'); | |
| if($passwordCheckFl != 'n') { | |
| $smsSender = \App::load(\Component\Sms\SmsSender::class); | |
| $smsSender->validPassword(\Request::post()->get('password')); | |
| } | |
| $passwordCheckFl = $passwordCheckFl == 'n' ? false : true; | |
| //쿠폰 지급 하는 코드 | |
| if($applyCoupon === true){ | |
| $applyCouponList = explode(INT_DIVISION, $this->group->get('groupCoupon')); | |
| foreach($applyCouponList as $value){ | |
| $coupon = new \Component\Coupon\CouponAdmin; | |
| \Request::post()->set('couponNo', $value); | |
| \Request::post()->set('couponSaveAdminId', '회원등급 쿠폰 혜택'); | |
| \Request::post()->set('managerNo', Session::get('manager.sno')); | |
| \Request::post()->set('memberCouponStartDate', $coupon->getMemberCouponStartDate($value)); | |
| \Request::post()->set('memberCouponEndDate', $coupon->getMemberCouponEndDate($value)); | |
| \Request::post()->set('memberCouponState', 'y'); | |
| $memberArr[] = $memNo; | |
| $coupon->saveMemberCouponSms($memberArr, null, $passwordCheckFl); | |
| unset($memberArr); | |
| } | |
| } | |
| $db = \App::getInstance('DB'); | |
| $fields = DBTableField::getFieldTypes('tableMember'); | |
| $arrUpdate[] = 'groupSno=?'; | |
| $arrBind = []; | |
| $db->bind_param_push($arrBind, $fields['groupSno'], $this->group->get('sno')); | |
| $arrUpdate[] = 'groupModDt=?'; | |
| $db->bind_param_push($arrBind, $fields['groupModDt'], $this->appraisalDateTime); | |
| $db->bind_param_push($arrBind, $fields['memNo'], $memNo); | |
| $db->bind_param_push($arrBind, $fields['appFl'], 'y'); | |
| $db->bind_param_push($arrBind, $fields['sleepFl'], 'n'); | |
| $db->set_update_db(DB_MEMBER, $arrUpdate, 'memNo = ? AND appFl = ? AND sleepFl = ?', $arrBind); | |
| } | |
| $limit = $this->search->getAppraisalLimit(); | |
| // 처리 반복 횟수 계산 | |
| $countByTotalMember = $this->appraisalCountByTotalMember($total, $limit); | |
| $logger = \App::getInstance('logger'); | |
| $logger->notice('Start apply coupon to all members.'); | |
| $logger->notice('총 회원[' . $total . '], 1회 처리당 제한 인원수[' . $limit . '], 처리 실행 횟수[' . $countByTotalMember . ']'); | |
| //그룹 설정 가져오기 | |
| $group = \App::load('Component\Member\Group\GroupDAO'); | |
| $passwordCheckFl = gd_isset(\Request::post()->get('passwordCheckFl'), 'y'); | |
| if($passwordCheckFl != 'n') { | |
| // 쿠폰 관리 객체 미리 생성 | |
| $coupon = new \Component\Coupon\CouponAdmin; | |
| // 그룹별 쿠폰 정보 캐시 | |
| $groupList = []; | |
| // 페이징 처리를 위한 반복문 | |
| for ($offset = 0; $offset < $countByTotalMember; $offset++) { | |
| $start = $offset * $limit; | |
| $logger->info(sprintf('Start apply coupon with offset %s, limit %s', $start, $limit)); | |
| // 페이지별 회원 목록 조회 | |
| $memberPageList = $member->getMemberList($arrWhere, null, null, $start, $limit, $field); | |
| if (!empty($memberPageList) && gd_count($memberPageList) > 0) { | |
| foreach ($memberPageList as $key => $value) { | |
| //그룹 정보 가져오기 (캐시 활용) | |
| if (empty($groupList[$value['groupSno']])) { | |
| $groupList[$value['groupSno']] = $group->selectGroup($value['groupSno'])['groupCoupon']; | |
| } | |
| //하나씩 쿠폰 발급 하기 | |
| if (!empty($groupList[$value['groupSno']]) && gd_count($groupList[$value['groupSno']]) > 0) { | |
| $applyCouponList = explode(INT_DIVISION, $groupList[$value['groupSno']]); | |
| } | |
| if (!empty($applyCouponList) && gd_count($applyCouponList) > 0) { | |
| \Request::post()->set('couponSaveAdminId', '회원등급 쿠폰 혜택'); | |
| \Request::post()->set('memberCouponState', 'y'); | |
| \Request::post()->set('managerNo', Session::get('manager.sno')); | |
| $memberArr[] = $value['memNo']; | |
| foreach ($applyCouponList as $applyCoupon) { | |
| if (is_numeric($applyCoupon) && $applyCoupon > 0) { | |
| \Request::post()->set('couponNo', $applyCoupon); | |
| \Request::post()->set('memberCouponStartDate', $coupon->getMemberCouponStartDate($applyCoupon)); | |
| \Request::post()->set('memberCouponEndDate', $coupon->getMemberCouponEndDate($applyCoupon)); | |
| $coupon->saveMemberCouponSms($memberArr, null, $passwordCheckFl); | |
| } | |
| } | |
| unset($memberArr, $applyCouponList); | |
| } | |
| } | |
| } | |
| // 메모리 정리 | |
| unset($memberPageList); | |
| } | |
| $logger->notice('End apply coupon to all members.'); | |
| } | |
| /** | |
| */ | |
| public function addSmsReceiver(SimpleStorage $storage, SimpleStorage $group) | |
| { | |
| $logger = \App::getInstance('logger'); | |
| if ($storage->get('cellPhone') != null && $storage->get('memNm') != null) { | |
| if ($storage->get('beforeGroupSno') != $group->get('sno')) { | |
| $smsAuto = \App::load(\Component\Sms\SmsAuto::class); | |
| 'memNm' => $storage->get('memNm'), | |
| 'memNo' => $storage->get('memNo'), | |
| 'groupNm' => $group->get('groupNm'), | |
| 'rc_mallNm' => $this->basicInfo['mallNm'], | |
| 'shopUrl' => $this->basicInfo['mallDomain'], | |
| ] | |
| ); | |
| $smsAuto->attach($observer); | |
| } else { | |
| $logger->info(sprintf('The membership level is the same. before[%d], now[%d]', $storage->get('beforeGroupSno'), $group->get('sno'))); | |
| } | |
| } else { | |
| $logger->info(sprintf('Not have a cell phone number or member name. memNo[%d]', $storage->get('memNo', 0))); | |
| } | |
| } | |
| { | |
| return $this->appraisalGroupConfig->get('apprSystem') == 'point'; | |
| } | |
| } | |
변경 후Appraisal.php
| namespace Bundle\Component\Member\Group; | |
| use App; | |
| use Component\Coupon\CouponAdmin; | |
| use Component\Database\DBTableField; | |
| use Component\Member\Member; | |
| use Component\Sms\Code; | |
| use Framework\Utility\ComponentUtils; | |
| use Framework\Utility\DateTimeUtils; | |
| use Framework\Utility\NumberUtils; | |
| use Origin\Service\Member\Group\MemberGroupCouponService; | |
| use Origin\Service\Member\Group\MemberGroupService; | |
| use Session; | |
| /** | |
| protected $search; | |
| /** @var AppraisalMailSender 등급평가 메일발송 */ | |
| protected $mailSender; | |
| /** @var string 등급평가일시 */ | |
| protected $appraisalDateTime; | |
| /** @var bool 현재 평가 등급 기준치 만족 여부 */ | |
| /** @var array 현재 평가대상 회원 */ | |
| protected $currentMembers; | |
| /** @var array 등급평가 제외 설정된 등급 sno 배열 */ | |
| protected $apprExclusionOfRating = []; | |
| /** @var array 평가 대상 그룹 sno별 등급 */ | |
| protected $groupSort; | |
| /** @var array 평가 대상 여부와 무관한 전체 그룹 sno별 등급 */ | |
| protected $allGroupSort = []; | |
| /** @var array 그룹 관리 설정 */ | |
| public $policy; | |
| /** @var array 기본 설정 */ | |
| public $basicInfo; | |
| /** @var string 수행일자 */ | |
| public $targetDateTime; | |
| /** @var array es_member 필드 타입 */ | |
| protected $memberFields; | |
| /** @var object 로거 */ | |
| protected $logger; | |
| /** @var CouponAdmin 쿠폰 어드민 (updateGroup 내 쿠폰 발급 재사용) */ | |
| protected $couponAdmin; | |
| /** @var array [couponNo => [memNo, ...]] — updateGroup에서 누적 후 flush 로 쿠폰별 일괄 발급 */ | |
| protected $couponSmsBuffer = []; | |
| /** @var array rollback 된 배치의 memNo — 유지회원 stamp 제외 대상 */ | |
| protected $rolledBackMemNos = []; | |
| /** | |
| * Appraisal constructor. | |
| * | |
| public function __construct(AppraisalSearch $search = null) | |
| { | |
| parent::__construct(); | |
| $this->memberFields = DBTableField::getFieldTypes('tableMember'); | |
| $this->logger = App::getInstance('logger'); | |
| $this->setSearch($search); | |
| $this->groupConfig(); | |
| $this->validateAppraisalGroupConfig(); | |
| $this->policy = ComponentUtils::getPolicy('member.group'); | |
| $this->basicInfo = gd_policy('basic.info'); | |
| $this->couponAdmin = new CouponAdmin(); | |
| ini_set('memory_limit', '-1'); | |
| } | |
| } | |
| if ($data['apprSystem'] == 'point' && $data['appraisalPointOrderPriceFl'] != 'y' && $data['appraisalPointOrderRepeatFl'] != 'y' && $data['appraisalPointReviewRepeatFl'] != 'y' && $data['appraisalPointLoginRepeatFl'] != 'y') { | |
| $this->logger->warning('Not set appraisal performance point'); | |
| throw new Exception(__('실적 점수제 평가 설정 값이 없습니다.')); | |
| } | |
| $this->appraisalGroupConfig = new SimpleStorage($data); | |
| $validation->validateOverlapStandard(); | |
| $this->groupSort[$group['sno']] = $group['groupSort']; // 그룹 key: sno, value: sort 배열 생성 | |
| } | |
| $this->allGroupSort = (array)$this->groupSort; | |
| if ($isAppraisalFigure) { | |
| foreach ($dao->selectAppraisalGroups() as $group) { | |
| $this->allGroupSort[$group['sno']] = $group['groupSort']; | |
| } | |
| } | |
| // 회원등급 평가시 제외인 등급 그룹 배열 생성 | |
| $exclusionGroups = $dao->selectGroupExclusion(); | |
| foreach ($exclusionGroups as $key){ | |
| $this->groupConfig = $groups; | |
| } | |
| /** | |
| * 직전 평가일(autoAppraisalDateTime)은 배치 완료 후에 갱신되므로, 평가주기만큼 전진시켜 이번 회차를 찾는다. | |
| * | |
| * @param string $targetDate Y-m-d | |
| * | |
| * @return string Y-m-d | |
| */ | |
| protected function resolveAppraisalCycleStartDate($targetDate) | |
| { | |
| $calcCycleDay = (int)$this->getPolicyValue('calcCycleDay'); | |
| $base = date_create((string)$targetDate); | |
| if ($calcCycleDay < 1 || $base === false) { | |
| return $targetDate; | |
| } | |
| $base = date_create($base->format('Y-m-d')); | |
| $cycleStart = $this->resolveCycleStartByPreviousAppraisal($base, $calcCycleDay); | |
| if ($cycleStart === null) { | |
| $cycleStart = $this->cycleDateInMonth($base, $calcCycleDay); | |
| if ($cycleStart > $base) { | |
| $cycleStart = $this->cycleDateInMonth($this->shiftMonth($base, -1), $calcCycleDay); | |
| } | |
| } | |
| return $cycleStart->format('Y-m-d'); | |
| } | |
| /** | |
| * @param \DateTime $base | |
| * @param int $calcCycleDay | |
| * | |
| * @return \DateTime|null | |
| */ | |
| protected function resolveCycleStartByPreviousAppraisal(\DateTime $base, $calcCycleDay) | |
| { | |
| $calcCycleMonth = (int)$this->getPolicyValue('calcCycleMonth'); | |
| $previous = (string)$this->getPolicyValue('autoAppraisalDateTime'); | |
| if ($calcCycleMonth < 1 || $previous === '') { | |
| return null; | |
| } | |
| $cycleStart = date_create($previous); | |
| if ($cycleStart === false) { | |
| return null; | |
| } | |
| $cycleStart = date_create($cycleStart->format('Y-m-d')); | |
| if ($cycleStart > $base) { | |
| return null; | |
| } | |
| while (true) { | |
| $next = $this->cycleDateInMonth($this->shiftMonth($cycleStart, $calcCycleMonth), $calcCycleDay); | |
| if ($next > $base) { | |
| return $cycleStart; | |
| } | |
| $cycleStart = $next; | |
| } | |
| } | |
| /** | |
| * @param \DateTime $base | |
| * @param int $months | |
| * | |
| * @return \DateTime | |
| */ | |
| protected function shiftMonth(\DateTime $base, $months) | |
| { | |
| return date_create($base->format('Y-m-01'))->modify(sprintf('%+d month', $months)); | |
| } | |
| /** | |
| * @param \DateTime $base | |
| * @param int $calcCycleDay | |
| * | |
| * @return \DateTime | |
| */ | |
| protected function cycleDateInMonth(\DateTime $base, $calcCycleDay) | |
| { | |
| $day = min($calcCycleDay, (int)$base->format('t')); | |
| return date_create($base->format('Y-m-') . sprintf('%02d', $day)); | |
| } | |
| /** | |
| * @param string $key | |
| * | |
| * @return mixed | |
| */ | |
| protected function getPolicyValue($key) | |
| { | |
| return isset($this->policy[$key]) ? $this->policy[$key] : ''; | |
| } | |
| /** | |
| * @param int $groupSno | |
| * | |
| * @return int | |
| */ | |
| protected function resolveGroupSort($groupSno) | |
| { | |
| if (array_key_exists($groupSno, $this->allGroupSort)) { | |
| return (int)$this->allGroupSort[$groupSno]; | |
| } | |
| if (array_key_exists($groupSno, (array)$this->groupSort)) { | |
| return (int)$this->groupSort[$groupSno]; | |
| } | |
| $this->logger->warning('Not found groupSort. groupSno[' . $groupSno . ']'); | |
| return 0; | |
| } | |
| /** | |
| * setGroupNames | |
| * @return void | |
| */ | |
| public function appraisalGroupBySearch() | |
| { | |
| $this->logger->notice('Start group appraisal.'); | |
| $total = $this->countTotalMember(); | |
| $limit = $this->search->getAppraisalLimit(); | |
| $this->countByTotalMember = $this->appraisalCountByTotalMember($total, $limit); | |
| $this->logger->notice('총 회원[' . $total . '], 1회 평가당 제한 인원수[' . $limit . '], 평가 실행 횟수[' . $this->countByTotalMember . ']'); | |
| $this->appraisalDateTime = DateTimeUtils::dateFormat('Y-m-d H:i:s', 'now'); | |
| if (method_exists($this->search, 'setRequiredData')) { | |
| $this->search->setRequiredData($this->resolveRequiredData()); | |
| } | |
| for ($offset = 0; $offset < $this->countByTotalMember; $offset++) { | |
| $this->appraisalGroupByOffset($offset); | |
| // 평가 대상으로 검색된 회원 초기화 | |
| $this->currentMembers = null; | |
| } | |
| $this->logger->notice('End group appraisal.'); | |
| } | |
| /** | |
| */ | |
| public function appraisalGroupByOffset($offset) | |
| { | |
| $db = \App::getInstance('DB'); | |
| $this->search->setAppraisalOffset($offset); | |
| if (method_exists($this->search, 'setTargetDateTime')) { | |
| $this->search->setTargetDateTime($this->targetDateTime); | |
| } | |
| $this->logger->info(sprintf('Start appraisal group set offset %s', $offset)); | |
| foreach ($this->groupConfig as $index => $item) { | |
| $this->logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| $this->group = new SimpleStorage($item); | |
| if ($this->currentMembers === null) { | |
| $this->currentMembers = $this->search->search($this->group); | |
| } | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $this->logger->info(sprintf('has appraisal member count is %d', count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } | |
| $this->logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| } | |
| if ($this->policy['downwardAdjustment'] == 'y') { | |
| $this->isDefaultGroupMember = true; | |
| $this->logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| $this->group = new SimpleStorage($this->defaultGroupConfig); | |
| $this->search->setAppraisalDateTime($this->appraisalDateTime); | |
| $this->currentMembers = $this->search->searchDefaultGroup($this->appraisalDateTime); | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $this->logger->info(sprintf('has appraisal member count is %d', count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } else { | |
| $this->logger->info('Not found appraisal members by default group', $this->defaultGroupConfig); | |
| } | |
| } | |
| $this->logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| $this->isDefaultGroupMember = false; | |
| } | |
| /** | |
| * 특정 회원에 대한 그룹평가 | |
| * | |
| * @param array $memNos 타겟 memNo 배열 | |
| * appraisalGroupBySearch() 와 appraisalGroupByOffset() deprecate 및 해당 메서드로 대체 필요 | |
| */ | |
| public function evaluateGroup(array $memNos) | |
| { | |
| if (empty($memNos)) { | |
| return; | |
| } | |
| if (!method_exists($this->search, 'setTargetMembers')) { | |
| throw new Exception('AppraisalSearch 구버전 : 자동 등급평가는 신규 setTargetMembers/setRequiredData/setTargetDateTime 메서드가 필요합니다. AppraisalSearch.php 를 코어와 동기화해주세요.'); | |
| } | |
| $this->logger->notice('Start group appraisal.'); | |
| $this->appraisalDateTime = DateTimeUtils::dateFormat('Y-m-d H:i:s', 'now'); | |
| $this->search->setTargetDateTime($this->targetDateTime); | |
| $this->search->setTargetMembers($memNos); | |
| $this->search->setRequiredData($this->resolveRequiredData()); | |
| foreach ($this->groupConfig as $index => $item) { | |
| $this->logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| $this->group = new SimpleStorage($item); | |
| if ($this->currentMembers === null) { | |
| $this->currentMembers = $this->search->search($this->group); | |
| } | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $this->logger->info(sprintf('has appraisal member count is %d', count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } | |
| $this->logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $item['groupNm'], $item['sno'], $item['groupSort'])); | |
| } | |
| if ($this->policy['downwardAdjustment'] == 'y') { | |
| $this->isDefaultGroupMember = true; | |
| $this->logger->info(sprintf('Start group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| $this->group = new SimpleStorage($this->defaultGroupConfig); | |
| $this->search->setAppraisalDateTime($this->appraisalDateTime); | |
| $this->currentMembers = $this->search->searchDefaultGroup($this->appraisalDateTime); | |
| if ($this->search->hasAppraisalMember($this->currentMembers)) { | |
| $this->logger->info(sprintf('has appraisal member count is %d', count($this->currentMembers))); | |
| $this->updateGroupWithAddMailReceiver($this->currentMembers); | |
| } else { | |
| $this->logger->info('Not found appraisal members by default group', $this->defaultGroupConfig); | |
| } | |
| $this->logger->info(sprintf('End group name is %s, group sno is %s, group sort is %s', $this->defaultGroupConfig['groupNm'], $this->defaultGroupConfig['sno'], $this->defaultGroupConfig['groupSort'])); | |
| } | |
| $this->isDefaultGroupMember = false; | |
| $this->logger->notice('End group appraisal.'); | |
| } | |
| /** | |
| * appraisalMailSend | |
| * @return void | |
| */ | |
| public function updateGroupWithAddMailReceiver(array $members) | |
| { | |
| $session = \App::getInstance('session'); | |
| $db = \App::getInstance('DB'); | |
| $updateTargetMemNos = []; | |
| $pendingReceivers = []; | |
| try { | |
| $groupSno = $this->group->get('sno'); | |
| $settleGb = $this->group->get('settleGb'); | |
| $smsSender = \App::load(\Component\Sms\SmsSender::class); | |
| $smsSender->validPassword(\Request::post()->get('password')); | |
| } | |
| $checkGroupByPoint = $this->_isAppraisalSystemPoint(); | |
| foreach ($members as $index => $item) { | |
| $session->set(Member::SESSION_MODIFY_MEMBER_INFO, $item); | |
| $storage = new SimpleStorage($item); | |
| $storage->set('settleGb', $settleGb); | |
| $memNo = $storage->get('memNo'); | |
| // 현재 등급이 '등급평가시 제외' 설정이 아닐 때 | |
| if(array_key_exists($item['groupSno'], $this->apprExclusionOfRating) == false) { | |
| if ($checkGroupByPoint) { | |
| $this->checkGroupByPoint($item); | |
| } else { | |
| $this->checkGroupByFigure($item); | |
| } | |
| $beforeGroupSort = $this->resolveGroupSort($item['groupSno']); | |
| $afterGroupSort = $this->resolveGroupSort($groupSno); | |
| //하향펑가를 설정하지 않았거나, 하향평가를 사용하거나, 하향평가를 사용하지 않고 변경 등급이 기존 등급보다 높거나 같을 때 만 업데이트 | |
| if (empty($this->policy['downwardAdjustment']) || $this->policy['downwardAdjustment'] == 'y' || ($this->policy['downwardAdjustment'] == 'n' && $beforeGroupSort < $afterGroupSort)) { | |
| if ($this->isCurrentGroupMember || $this->isDefaultGroupMember) { | |
| $this->logger->info('Group change target. sno[' . $this->group->get('sno', 0) . '], name[' . $this->group->get('', '-') . ']', $item); | |
| $updateTargetMemNos[] = $memNo; | |
| $this->updateGroup($memNo); | |
| $this->writeHistory($memNo); | |
| $pendingReceivers[] = $storage; | |
| unset($members[$index]); | |
| } | |
| } | |
| } | |
| } | |
| // 쿠폰 발급은 회원 1명씩 호출하는 대신 쿠폰 번호별로 memNos 를 묶어 일괄 호출 | |
| if (!method_exists($this, 'flushCouponSmsBuffer')) { | |
| throw new Exception('Appraisal 구버전 감지: flushCouponSmsBuffer 메서드 누락. 등급평가 쿠폰 버퍼 일괄발급 로직 미적용 시 쿠폰 미발급이 발생할 수 있어 사전 차단합니다.'); | |
| } | |
| $this->flushCouponSmsBuffer(); | |
| if ($this->isTran) { | |
| $db->commit(); | |
| $this->currentMembers = $members; | |
| } | |
| foreach ($pendingReceivers as $receiver) { | |
| $this->addMailReceiver($receiver, $this->group); | |
| $this->addSmsReceiver($receiver, $this->group); | |
| } | |
| } catch (Exception $e) { | |
| $this->logger->error(__METHOD__ . ', ' . $e->getMessage(), ['exception' => $e]); | |
| $db->rollback(); | |
| $this->couponSmsBuffer = []; | |
| $this->rolledBackMemNos = array_merge($this->rolledBackMemNos, $updateTargetMemNos); | |
| if (method_exists($this->search, 'removeEvaluatedMemberSnapshots')) { | |
| $this->search->removeEvaluatedMemberSnapshots($updateTargetMemNos); | |
| } | |
| } | |
| } | |
| /** | |
| * @deprecated 반복문 내 다중 호출 시 성능 저하가 발생하므로 | |
| * 반복문 밖에서 한 번만 호출하여 결과를 캐싱해 사용하세요. | |
| * 향후 내부 로직에서 캐싱되거나 제거될 예정입니다. | |
| * | |
| * @param array $item 등급평가 대상의 기준치 정보 | |
| * | |
| } | |
| } | |
| if ($point > 0) { | |
| $this->logger->info( | |
| __METHOD__, [ | |
| 'memNo:'.$memNo, | |
| $point, | |
| */ | |
| public function checkGroupByFigure($item) | |
| { | |
| $this->isCurrentGroupMember = true; | |
| $priceUnit = 10000; | |
| */ | |
| public function updateGroupWithInsertHistory(SimpleStorage $storage) | |
| { | |
| $passwordCheckFl = gd_isset(\Request::post()->get('passwordCheckFl'), 'y'); | |
| if ($passwordCheckFl != 'n') { | |
| $smsSender = \App::load(\Component\Sms\SmsSender::class); | |
| $smsSender->validPassword(\Request::post()->get('password')); | |
| } | |
| $memNo = $storage->get('memNo'); | |
| $this->updateGroup($memNo); | |
| $this->writeHistory($memNo); | |
| if (!method_exists($this, 'flushCouponSmsBuffer')) { | |
| throw new Exception('Appraisal 구버전 감지: flushCouponSmsBuffer 메서드 누락. 등급평가 쿠폰 버퍼 일괄발급 로직 미적용 시 쿠폰 미발급이 발생할 수 있어 사전 차단합니다.'); | |
| } | |
| $this->flushCouponSmsBuffer(); | |
| } | |
| /** | |
| * updateGroup 루프에서 쌓인 쿠폰 발급 대상을 쿠폰 번호별로 묶어 일괄 발급. | |
| * 호출당 saveMemberCouponSms 내부 셋업 쿼리 (checkCouponType, getCouponInfo, | |
| * getMemberCouponStartDate/EndDate) 를 회원 수가 아닌 쿠폰 수 만큼만 수행. | |
| * | |
| * @return void | |
| */ | |
| public function flushCouponSmsBuffer() | |
| { | |
| if (empty($this->couponSmsBuffer)) { | |
| return; | |
| } | |
| $passwordCheckFlBool = \Request::post()->get('passwordCheckFl') == 'n' ? false : true; | |
| \Request::post()->set('couponSaveAdminId', '회원등급 쿠폰 혜택'); | |
| \Request::post()->set('managerNo', Session::get('manager.sno')); | |
| \Request::post()->set('memberCouponState', 'y'); | |
| foreach ($this->couponSmsBuffer as $couponNo => $memNos) { | |
| \Request::post()->set('couponNo', $couponNo); | |
| $result = $this->couponAdmin->saveMemberCouponSms($memNos, null, $passwordCheckFlBool); | |
| if ($result === false) { | |
| $this->logger->warning(sprintf('Coupon issue skipped (checkCouponType failed). couponNo[%d] memNo_cnt[%d]', $couponNo, count($memNos))); | |
| } | |
| } | |
| $this->couponSmsBuffer = []; | |
| } | |
| /** | |
| } | |
| } | |
| //쿠폰 지급 대상 버퍼에 적재 (실제 발급은 flushCouponSmsBuffer 에서 쿠폰별 일괄 호출) | |
| if($applyCoupon === true){ | |
| foreach(explode(INT_DIVISION, $this->group->get('groupCoupon')) as $value){ | |
| $couponNo = (int)$value; | |
| if ($couponNo > 0) { | |
| $this->couponSmsBuffer[$couponNo][] = $memNo; | |
| } | |
| } | |
| } | |
| $db = \App::getInstance('DB'); | |
| $arrUpdate[] = 'groupSno = ?'; | |
| $arrBind = []; | |
| $db->bind_param_push($arrBind, $this->memberFields['groupSno'], $this->group->get('sno')); | |
| $arrUpdate[] = 'groupModDt = ?'; | |
| $db->bind_param_push($arrBind, $this->memberFields['groupModDt'], $this->appraisalDateTime); | |
| $arrUpdate[] = 'autoGroupAppraisalDt = ?'; | |
| $db->bind_param_push($arrBind, $this->memberFields['autoGroupAppraisalDt'], $this->appraisalDateTime); | |
| $db->bind_param_push($arrBind, $this->memberFields['memNo'], $memNo); | |
| $db->bind_param_push($arrBind, $this->memberFields['appFl'], 'y'); | |
| $db->bind_param_push($arrBind, $this->memberFields['sleepFl'], 'n'); | |
| $db->set_update_db(DB_MEMBER, $arrUpdate, 'memNo = ? AND appFl = ? AND sleepFl = ?', $arrBind); | |
| } | |
| $limit = $this->search->getAppraisalLimit(); | |
| // 처리 반복 횟수 계산 | |
| $countByTotalMember = $this->appraisalCountByTotalMember($total, $limit); | |
| $this->logger->notice('Start apply coupon to all members.'); | |
| $this->logger->notice('총 회원[' . $total . '], 1회 처리당 제한 인원수[' . $limit . '], 처리 실행 횟수[' . $countByTotalMember . ']'); | |
| $passwordCheckFl = gd_isset(\Request::post()->get('passwordCheckFl'), 'y'); | |
| if($passwordCheckFl != 'n') { | |
| // 쿠폰 관리 객체 미리 생성 | |
| $coupon = new \Component\Coupon\CouponAdmin; | |
| // 쿠폰 정보 미리 생성 | |
| \Request::post()->set('couponSaveAdminId', '회원등급 쿠폰 혜택'); | |
| \Request::post()->set('memberCouponState', 'y'); | |
| \Request::post()->set('managerNo', Session::get('manager.sno')); | |
| // 그룹 쿠폰 정보 | |
| /** @var MemberGroupService $memberGroupService */ | |
| $memberGroupService = App::getInstance(MemberGroupService::class); | |
| $allGroupList = $memberGroupService->findAllGroupsKeyBySno(); | |
| // 페이징 처리를 위한 반복문 | |
| for ($offset = 0; $offset < $countByTotalMember; $offset++) { | |
| $start = $offset * $limit; | |
| $this->logger->info(sprintf('Start apply coupon with offset %s, limit %s', $start, $limit)); | |
| // 페이지별 회원 목록 조회 | |
| $memberPageList = $member->getMemberList($arrWhere, null, null, $start, $limit, $field); | |
| if (count($memberPageList) === 0) { | |
| continue; | |
| } | |
| foreach ($memberPageList as $memberInfo) { | |
| $groupCoupon = $allGroupList[$memberInfo['groupSno']]['groupCoupon'] ?? ''; | |
| if (empty($groupCoupon)) { | |
| continue; | |
| } | |
| $applyCouponList = explode(INT_DIVISION, $groupCoupon); | |
| // 하나씩 쿠폰 발급 하기 | |
| if (!empty($applyCouponList) && count($applyCouponList) > 0) { | |
| foreach ($applyCouponList as $applyCoupon) { | |
| if (is_numeric($applyCoupon) && $applyCoupon > 0) { | |
| \Request::post()->set('couponNo', $applyCoupon); | |
| \Request::post()->set('memberCouponStartDate', $coupon->getMemberCouponStartDate($applyCoupon)); | |
| \Request::post()->set('memberCouponEndDate', $coupon->getMemberCouponEndDate($applyCoupon)); | |
| $coupon->saveMemberCouponSms((array)$memberInfo['memNo'], null, $passwordCheckFl); | |
| } | |
| } | |
| unset($applyCouponList); | |
| } | |
| } | |
| // 메모리 정리 | |
| unset($memberPageList); | |
| } | |
| $this->logger->notice('End apply coupon to all members.'); | |
| } | |
| /** | |
| * 특정 회원에게 쿠폰 발급 | |
| * - 이미 등급평가를 통해 쿠폰이 발급된 회원 제외 | |
| * | |
| * applyCouponAllMember() 를 deprecate 및 해당 메서드로 대체 필요 | |
| * @param string $targetDate 대상일자 | |
| * @param array $memNos 대상 회원번호 배열 | |
| * | |
| * @return void | |
| */ | |
| public function applyCouponSpecificMember(string $targetDate, array $memNos) | |
| { | |
| if (empty($memNos)) { | |
| return; | |
| } | |
| $this->logger->notice('Start apply coupon to specific members.'); | |
| $passwordCheckFl = gd_isset(\Request::post()->get('passwordCheckFl'), 'y'); | |
| if($passwordCheckFl != 'n') { | |
| $smsSender = \App::load(\Component\Sms\SmsSender::class); | |
| $smsSender->validPassword(\Request::post()->get('password')); | |
| } | |
| $passwordCheckFl = $passwordCheckFl == 'n' ? false : true; | |
| // 쿠폰의 경우 재수행되었을 때 구분할 수 있는 값이 필요하여 대상일자를 추가함 | |
| $couponSaveAdminId = '회원등급 쿠폰 혜택(' . str_replace('-','', $targetDate) . ')'; | |
| \Request::post()->set('couponSaveAdminId', $couponSaveAdminId); | |
| \Request::post()->set('memberCouponState', 'y'); | |
| \Request::post()->set('managerNo', Session::get('manager.sno')); | |
| /** @var MemberGroupCouponService $memberGroupCouponService */ | |
| $memberGroupCouponService = App::getInstance(MemberGroupCouponService::class); | |
| $memberGroupCouponService->applyGroupCouponsToMembers( | |
| $memNos, | |
| $couponSaveAdminId, | |
| $passwordCheckFl, | |
| $targetDate, | |
| $this->resolveAppraisalCycleStartDate($targetDate) | |
| ); | |
| } | |
| /** | |
| * 변경자는 updateGroup 에서 이미 stamp 되므로, 유지자만 보완해 동일자 재평가 대상에서 제외되도록 한다. | |
| * | |
| * @param array $memNos | |
| * @param string $targetDate Y-m-d | |
| * | |
| * @return void | |
| */ | |
| public function updateAppraisalCompletedForDefaultGroupMembers(array $memNos, string $targetDate) | |
| { | |
| if (empty($memNos)) { | |
| return; | |
| } | |
| if (!method_exists($this->search, 'getEvaluatedMemberSnapshots')) { | |
| throw new Exception('AppraisalSearch 구버전 감지: getEvaluatedMemberSnapshots 누락. 평가 스냅샷 없이 유지회원 stamp 시 미평가 회원까지 평가완료 처리되어 다음 회차에서 누락될 수 있어 사전 차단합니다.'); | |
| } | |
| $db = \App::getInstance('DB'); | |
| $touchDateTime = $this->appraisalDateTime ?: ($targetDate . ' 00:00:00'); | |
| $from = $targetDate . ' 00:00:00'; | |
| $snapshots = $this->search->getEvaluatedMemberSnapshots(); | |
| $exclusion = $this->apprExclusionOfRating ?? []; | |
| $appraisalGroupSnos = $this->resolveAppraisalGroupSnos(); | |
| if (empty($appraisalGroupSnos)) { | |
| $this->logger->warning('Skip retained member stamp. Not found appraisal target group.', [ | |
| 'groupSort' => $this->groupSort, | |
| 'exclusion' => $exclusion, | |
| ]); | |
| return; | |
| } | |
| if (empty($snapshots)) { | |
| // 평가 검색이 실행되지 않은 실행(평가기준 그룹 없음 등) — 종전 라이브 조회 방식으로 stamp | |
| $memNos = array_values(array_diff($memNos, $this->rolledBackMemNos)); | |
| if (empty($memNos)) { | |
| return; | |
| } | |
| $arrBind = []; | |
| $db->bind_param_push($arrBind, 's', $touchDateTime); | |
| $placeholders = implode(',', array_fill(0, count($memNos), '?')); | |
| foreach ($memNos as $memNo) { | |
| $db->bind_param_push($arrBind, 'i', $memNo); | |
| } | |
| $db->bind_param_push($arrBind, 's', 'y'); | |
| $db->bind_param_push($arrBind, 's', 'n'); | |
| $groupPlaceholders = implode(',', array_fill(0, count($appraisalGroupSnos), '?')); | |
| foreach ($appraisalGroupSnos as $sno) { | |
| $db->bind_param_push($arrBind, 'i', $sno); | |
| } | |
| $db->bind_param_push($arrBind, 's', $from); | |
| $strWhere = 'memNo IN (' . $placeholders . ')' | |
| . ' AND appFl = ?' | |
| . ' AND sleepFl = ?' | |
| . ' AND groupSno IN (' . $groupPlaceholders . ')' | |
| . ' AND (autoGroupAppraisalDt IS NULL OR autoGroupAppraisalDt < ?)'; | |
| $db->set_update_db(DB_MEMBER, 'autoGroupAppraisalDt = ?', $strWhere, $arrBind); | |
| $this->logger->info('Update autoGroupAppraisalDt for retained members (no snapshot fallback)', [ | |
| 'table' => DB_MEMBER, | |
| 'memNoCount' => count($memNos), | |
| 'from' => $from, | |
| ]); | |
| return; | |
| } | |
| $retainedMemNos = $this->resolveRetainedStampTargets($snapshots, $exclusion, $appraisalGroupSnos); | |
| if (empty($retainedMemNos)) { | |
| return; | |
| } | |
| $arrBind = []; | |
| $db->bind_param_push($arrBind, 's', $touchDateTime); | |
| $placeholders = implode(',', array_fill(0, count($retainedMemNos), '?')); | |
| foreach ($retainedMemNos as $memNo) { | |
| $db->bind_param_push($arrBind, 'i', $memNo); | |
| } | |
| $db->bind_param_push($arrBind, 's', 'y'); | |
| $db->bind_param_push($arrBind, 's', 'n'); | |
| $db->bind_param_push($arrBind, 's', $from); | |
| $strWhere = 'memNo IN (' . $placeholders . ')' | |
| . ' AND appFl = ?' | |
| . ' AND sleepFl = ?' | |
| . ' AND (autoGroupAppraisalDt IS NULL OR autoGroupAppraisalDt < ?)'; | |
| $db->set_update_db(DB_MEMBER, 'autoGroupAppraisalDt = ?', $strWhere, $arrBind); | |
| $this->logger->info('Update autoGroupAppraisalDt for retained members', [ | |
| 'table' => DB_MEMBER, | |
| 'memNoCount' => count($retainedMemNos), | |
| 'from' => $from, | |
| ]); | |
| } | |
| /** | |
| * @param array $snapshots memNo => search 결과 row | |
| * @param array $exclusion 제외그룹 sno => sno | |
| * @param array $appraisalGroupSnos 평가 대상 등급 sno 배열 | |
| * | |
| * @return array | |
| */ | |
| public function resolveRetainedStampTargets(array $snapshots, array $exclusion, array $appraisalGroupSnos) | |
| { | |
| $retainedMemNos = []; | |
| $appraisalGroupSnos = array_map('intval', $appraisalGroupSnos); | |
| foreach ($snapshots as $memNo => $row) { | |
| $groupSno = is_array($row) ? ($row['groupSno'] ?? null) : null; | |
| if ($groupSno !== null && array_key_exists($groupSno, $exclusion)) { | |
| continue; | |
| } | |
| if ($groupSno !== null && in_array((int)$groupSno, $appraisalGroupSnos, true) === false) { | |
| continue; | |
| } | |
| $retainedMemNos[] = (int)$memNo; | |
| } | |
| return $retainedMemNos; | |
| } | |
| /** | |
| * @return array | |
| */ | |
| public function resolveAppraisalGroupSnos() | |
| { | |
| $groupSnos = array_keys((array)$this->groupSort); | |
| $exclusionSnos = array_values((array)$this->apprExclusionOfRating); | |
| return array_values(array_diff($groupSnos, $exclusionSnos)); | |
| } | |
| /** | |
| */ | |
| public function addSmsReceiver(SimpleStorage $storage, SimpleStorage $group) | |
| { | |
| if ($storage->get('cellPhone') != null && $storage->get('memNm') != null) { | |
| if ($storage->get('beforeGroupSno') != $group->get('sno')) { | |
| $smsAuto = \App::load(\Component\Sms\SmsAuto::class); | |
| 'memNm' => $storage->get('memNm'), | |
| 'memNo' => $storage->get('memNo'), | |
| 'groupNm' => $group->get('groupNm'), | |
| 'rc_mallNm' => \Globals::get('gMall.mallNm'), | |
| 'shopUrl' => $this->basicInfo['mallDomain'], | |
| ] | |
| ); | |
| $smsAuto->attach($observer); | |
| } else { | |
| $this->logger->info(sprintf('The membership level is the same. before[%d], now[%d]', $storage->get('beforeGroupSno'), $group->get('sno'))); | |
| } | |
| } else { | |
| $this->logger->info(sprintf('Not have a cell phone number or member name. memNo[%d]', $storage->get('memNo', 0))); | |
| } | |
| } | |
| { | |
| return $this->appraisalGroupConfig->get('apprSystem') == 'point'; | |
| } | |
| /* | |
| * 회원등급평가 타겟일자 셋팅 | |
| * | |
| * @param $targetDateTime 수행일자 | |
| */ | |
| public function setTargetDateTime($targetDateTime = null) | |
| { | |
| $this->targetDateTime = empty($targetDateTime) ? date('Y-m-d') : $targetDateTime; | |
| } | |
| /** | |
| * 전체 등급 설정을 스캔하여 실제 필요한 데이터 유형을 결정 | |
| * @return array ['order' => bool, 'review' => bool, 'login' => bool] | |
| */ | |
| protected function resolveRequiredData(): array | |
| { | |
| $isPoint = $this->_isAppraisalSystemPoint(); | |
| if ($isPoint) { | |
| return [ | |
| 'order' => $this->appraisalGroupConfig->get('appraisalPointOrderPriceFl', 'n') == 'y' | |
| || $this->appraisalGroupConfig->get('appraisalPointOrderRepeatFl', 'n') == 'y', | |
| 'review' => $this->appraisalGroupConfig->get('appraisalPointReviewRepeatFl', 'n') == 'y', | |
| 'login' => $this->appraisalGroupConfig->get('appraisalPointLoginRepeatFl', 'n') == 'y', | |
| ]; | |
| } | |
| // 수치제: 등급별 설정이므로 전체 등급을 스캔 | |
| $allGroups = array_merge($this->groupConfig, [$this->defaultGroupConfig]); | |
| $needsOrder = false; | |
| $needsReview = false; | |
| foreach ($allGroups as $group) { | |
| if (!$needsOrder && (($group['apprFigureOrderPriceFl'] ?? 'n') == 'y' || ($group['apprFigureOrderRepeatFl'] ?? 'n') == 'y')) { | |
| $needsOrder = true; | |
| } | |
| if (!$needsReview && ($group['apprFigureReviewRepeatFl'] ?? 'n') == 'y') { | |
| $needsReview = true; | |
| } | |
| if ($needsOrder && $needsReview) { | |
| break; | |
| } | |
| } | |
| return [ | |
| 'order' => $needsOrder, | |
| 'review' => $needsReview, | |
| 'login' => false, // 수치제에서는 로그인 기준 없음 | |
| ]; | |
| } | |
| } | |
변경 전AppraisalSearch.php
| private $periodQuery; | |
| /** @var string $periodDateFormat 검색기간 포맷 */ | |
| private $periodDateFormat = 'Y-m-d'; | |
| /** | |
| * 조회 | |
| unset($this->query, $this->column, $this->where); | |
| $this->periodQuery(); | |
| $this->boardQuery(); | |
| $this->orderQuery(); | |
| $this->loginQuery(); | |
| $this->buildQuery(); | |
| $logger->info(sprintf('Build query complete. %s', $this->query)); | |
| $results = $this->db->query_fetch($this->query); | |
| $logger->debug('Appraisal search result keys', gd_array_keys($results[0])); | |
| $return = []; | |
| foreach ($results as $index => $result) { | |
| if (gd_array_key_exists($result['memNo'], $return)) { | |
| $return[$result['memNo']] = $result; | |
| } | |
| return $return; | |
| } | |
| $query[] = 'SELECT memNo, COUNT(sno) AS cnt'; | |
| $query[] = ', COUNT(IF(loginCntMobile > 0, 1, NULL)) AS mcnt'; | |
| $query[] = 'FROM ' . DB_MEMBER_LOGINLOG; | |
| if ($this->usePeriod()) { | |
| $query[] = 'WHERE regDt ' . $this->periodQuery; | |
| } | |
| $query[] = 'GROUP BY memNo'; | |
| $this->loginQuery = '(' . gd_implode(' ', $query) . ')'; | |
| $query[] = ', COUNT(IF(isMobile=\'y\', sno, NULL)) AS mcnt'; | |
| $query[] = 'FROM ' . DB_BD_ . Board::BASIC_GOODS_REIVEW_ID; | |
| $query[] = 'WHERE memNo > 0'; | |
| if ($this->usePeriod()) { | |
| $query[] = 'AND regDt ' . $this->periodQuery; | |
| } | |
| $subQuery[] = 'LEFT JOIN ' . DB_ORDER_GOODS . ' AS og ON o.orderNo = og.orderNo'; | |
| $subQuery[] = 'LEFT JOIN ' . DB_ORDER_ADD_GOODS . ' AS oag ON o.orderNo = oag.orderNo'; | |
| $subQuery[] = 'WHERE og.orderStatus=\'s1\' AND o.memNo > 0'; | |
| if ($this->usePeriod()) { | |
| $subQuery[] = 'AND og.finishDt ' . $this->periodQuery; | |
| } | |
| unset($this->query, $this->column, $this->where); | |
| $this->periodQuery(); | |
| $this->boardQuery(); | |
| $this->orderQuery(); | |
| $this->loginQuery(); | |
| $this->buildQuery('m.groupSno!=' . $groupSno); | |
| $logger = \App::getInstance('logger'); | |
| $logger->info(sprintf('Build query complete. %s', $this->query)); | |
| */ | |
| public function searchDefaultGroup($appraisalDateTime) | |
| { | |
| $this->db->strField = 'm.memNo, m.memNm, m.email, m.cellPhone, m.groupSno, m.adminMemo, m.groupModDt'; | |
| // 다른등급 대상 회원 조회(_pushWhere())와 조건 동일하게 설정 | |
| $this->db->strWhere = 'm.sleepFl=\'n\' AND m.appFl=\'y\''; | |
| $this->db->strLimit = ($this->appraisalOffset * $this->appraisalLimit) . ', ' . $this->appraisalLimit; | |
| $this->db->strGroup = 'm.memNo'; | |
| $query = $this->db->query_complete(); | |
| $return[$result['memNo']] = $result; | |
| } | |
| } | |
| return $return; | |
| } | |
| if (!empty($where)) { | |
| $this->where[] = $where; | |
| } | |
| $this->db->strField = gd_implode(',', $this->column); | |
| $this->db->strWhere = gd_implode(' AND ', $this->where); | |
| $this->db->strJoin = 'LEFT JOIN ' . $this->boardQuery . ' AS b ON m.memNo = b.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . $this->orderQuery . ' AS o ON m.memNo = o.memNo'; | |
| $this->db->strJoin .= ' LEFT JOIN ' . $this->loginQuery . ' AS l ON m.memNo = l.memNo'; | |
| $this->db->strLimit = ($this->appraisalOffset * $this->appraisalLimit) . ', ' . $this->appraisalLimit; | |
| $this->db->strGroup = 'm.memNo'; | |
| $query = $this->db->query_complete(); | |
| */ | |
| private function _pushColumn() | |
| { | |
| $this->column[] = 'm.memNo, m.memNm, m.email, m.cellPhone, m.groupSno, m.adminMemo, m.groupModDt'; | |
| $this->column[] = 'IFNULL(l.cnt, 0) AS loginCount'; | |
| $this->column[] = 'IFNULL(b.cnt, 0) AS reviewCount'; | |
| $this->column[] = 'IFNULL(o.cnt, 0) AS orderCount'; | |
| $this->column[] = 'IFNULL(o.price, 0) AS orderPrice'; | |
| $this->column[] = 'IFNULL(l.mcnt, 0) AS loginCountMobile'; | |
| $this->column[] = 'IFNULL(b.mcnt, 0) AS reviewCountMobile'; | |
| $this->column[] = 'IFNULL(o.mcnt, 0) AS orderCountMobile'; | |
| $this->column[] = 'IFNULL(o.mprice, 0) AS orderPriceMobile'; | |
| } | |
| /** | |
| $column = 'IFNULL(' . $column . ', 0)'; | |
| } | |
| } | |
| } | |
변경 후AppraisalSearch.php
| private $periodQuery; | |
| /** @var string $periodDateFormat 검색기간 포맷 */ | |
| private $periodDateFormat = 'Y-m-d'; | |
| /** @var string 수행일자 */ | |
| protected $targetDateTime; | |
| /** @var array airflow 가 지정한 memNo 배열 */ | |
| protected $targetMembers = []; | |
| /** @var array 실제 평가된 회원 스냅샷 (memNo => search 결과 row). 유지회원 stamp 대상 판정 기준 */ | |
| protected $evaluatedMembers = []; | |
| /** @var array 필요한 서브쿼리 플래그 ['order' => bool, 'review' => bool, 'login' => bool] */ | |
| protected $requiredData = ['order' => true, 'review' => true, 'login' => true]; | |
| /** | |
| * 조회 | |
| unset($this->query, $this->column, $this->where); | |
| $this->periodQuery(); | |
| if ($this->requiredData['review']) { | |
| $this->boardQuery(); | |
| } | |
| if ($this->requiredData['order']) { | |
| $this->orderQuery(); | |
| } | |
| if ($this->requiredData['login']) { | |
| $this->loginQuery(); | |
| } | |
| // 수동평가(targetMembers 없음)는 동일자 재평가 허용을 위해 완료대상 제외 필터 미적용 | |
| $this->buildQuery(empty($this->targetMembers) ? '' : $this->whereExcludeCompleteMember()); | |
| $logger->info(sprintf('Build query complete. %s', $this->query)); | |
| $results = $this->db->query_fetch($this->query); | |
| $logger->debug('Appraisal search result keys', empty($results) ? [] : array_keys($results[0])); | |
| $return = []; | |
| foreach ($results as $index => $result) { | |
| if (gd_array_key_exists($result['memNo'], $return)) { | |
| $return[$result['memNo']] = $result; | |
| } | |
| $logger->info(sprintf('Appraisal search matched %d of %d requested members. groupSno[%s]', count($return), count($this->targetMembers), $group->get('sno', '-'))); | |
| if (!empty($this->targetMembers)) { | |
| foreach ($return as $memNo => $row) { | |
| $this->evaluatedMembers[$memNo] = $row; | |
| } | |
| } | |
| return $return; | |
| } | |
| $query[] = 'SELECT memNo, COUNT(sno) AS cnt'; | |
| $query[] = ', COUNT(IF(loginCntMobile > 0, 1, NULL)) AS mcnt'; | |
| $query[] = 'FROM ' . DB_MEMBER_LOGINLOG; | |
| $loginWhere = []; | |
| if ($this->usePeriod()) { | |
| $loginWhere[] = 'regDt ' . $this->periodQuery; | |
| } | |
| if (!empty($this->targetMembers)) { | |
| $loginWhere[] = 'memNo IN (' . implode(',', array_map('intval', $this->targetMembers)) . ')'; | |
| } | |
| if (!empty($loginWhere)) { | |
| $query[] = 'WHERE ' . implode(' AND ', $loginWhere); | |
| } | |
| $query[] = 'GROUP BY memNo'; | |
| $this->loginQuery = '(' . gd_implode(' ', $query) . ')'; | |
| $query[] = ', COUNT(IF(isMobile=\'y\', sno, NULL)) AS mcnt'; | |
| $query[] = 'FROM ' . DB_BD_ . Board::BASIC_GOODS_REIVEW_ID; | |
| $query[] = 'WHERE memNo > 0'; | |
| if (!empty($this->targetMembers)) { | |
| $query[] = 'AND memNo IN (' . implode(',', array_map('intval', $this->targetMembers)) . ')'; | |
| } | |
| if ($this->usePeriod()) { | |
| $query[] = 'AND regDt ' . $this->periodQuery; | |
| } | |
| $subQuery[] = 'LEFT JOIN ' . DB_ORDER_GOODS . ' AS og ON o.orderNo = og.orderNo'; | |
| $subQuery[] = 'LEFT JOIN ' . DB_ORDER_ADD_GOODS . ' AS oag ON o.orderNo = oag.orderNo'; | |
| $subQuery[] = 'WHERE og.orderStatus=\'s1\' AND o.memNo > 0'; | |
| if (!empty($this->targetMembers)) { | |
| $subQuery[] = 'AND o.memNo IN (' . implode(',', array_map('intval', $this->targetMembers)) . ')'; | |
| } | |
| if ($this->usePeriod()) { | |
| $subQuery[] = 'AND og.finishDt ' . $this->periodQuery; | |
| } | |
| unset($this->query, $this->column, $this->where); | |
| $this->periodQuery(); | |
| if ($this->requiredData['review']) { | |
| $this->boardQuery(); | |
| } | |
| if ($this->requiredData['order']) { | |
| $this->orderQuery(); | |
| } | |
| if ($this->requiredData['login']) { | |
| $this->loginQuery(); | |
| } | |
| $where = 'm.groupSno != ' . $groupSno; | |
| if (!empty($this->targetMembers)) { | |
| $where .= ' AND ' . $this->whereExcludeCompleteMember(); | |
| } | |
| $this->buildQuery($where); | |
| $logger = \App::getInstance('logger'); | |
| $logger->info(sprintf('Build query complete. %s', $this->query)); | |
| */ | |
| public function searchDefaultGroup($appraisalDateTime) | |
| { | |
| $this->db->strField = 'm.memNo, m.memNm, m.email, m.cellPhone, m.smsFl, m.maillingFl, m.groupSno, m.adminMemo, m.groupModDt'; | |
| // 다른등급 대상 회원 조회(_pushWhere())와 조건 동일하게 설정 | |
| $this->db->strWhere = 'm.sleepFl=\'n\' AND m.appFl=\'y\''; | |
| if (!empty($this->targetMembers)) { | |
| $this->db->strWhere .= ' AND ' . $this->whereExcludeCompleteMember(); | |
| } | |
| if (empty($this->targetMembers)) { | |
| $this->db->strLimit = ($this->appraisalOffset * $this->appraisalLimit) . ', ' . $this->appraisalLimit; | |
| } else { | |
| $this->db->strWhere .= ' AND m.memNo IN (' . implode(',', array_map('intval', $this->targetMembers)) . ')'; | |
| } | |
| $this->db->strGroup = 'm.memNo'; | |
| $query = $this->db->query_complete(); | |
| $return[$result['memNo']] = $result; | |
| } | |
| } | |
| return $return; | |
| } | |
| if (!empty($where)) { | |
| $this->where[] = $where; | |
| } | |
| $this->db->strField = implode(',', $this->column); | |
| $this->db->strWhere = implode(' AND ', $this->where); | |
| $joins = []; | |
| if ($this->requiredData['review']) { | |
| $joins[] = 'LEFT JOIN ' . $this->boardQuery . ' AS b ON m.memNo = b.memNo'; | |
| } | |
| if ($this->requiredData['order']) { | |
| $joins[] = 'LEFT JOIN ' . $this->orderQuery . ' AS o ON m.memNo = o.memNo'; | |
| } | |
| if ($this->requiredData['login']) { | |
| $joins[] = 'LEFT JOIN ' . $this->loginQuery . ' AS l ON m.memNo = l.memNo'; | |
| } | |
| $this->db->strJoin = implode(' ', $joins); | |
| if (empty($this->targetMembers)) { | |
| $this->db->strLimit = ($this->appraisalOffset * $this->appraisalLimit) . ', ' . $this->appraisalLimit; | |
| } else { | |
| $this->db->strWhere .= ' AND m.memNo IN (' . implode(',', array_map('intval', $this->targetMembers)) . ')'; | |
| } | |
| $this->db->strGroup = 'm.memNo'; | |
| $query = $this->db->query_complete(); | |
| */ | |
| private function _pushColumn() | |
| { | |
| $this->column[] = 'm.memNo, m.memNm, m.email, m.cellPhone, m.smsFl, m.maillingFl, m.groupSno, m.adminMemo, m.groupModDt'; | |
| if ($this->requiredData['login']) { | |
| $this->column[] = 'IFNULL(l.cnt, 0) AS loginCount'; | |
| $this->column[] = 'IFNULL(l.mcnt, 0) AS loginCountMobile'; | |
| } else { | |
| $this->column[] = '0 AS loginCount'; | |
| $this->column[] = '0 AS loginCountMobile'; | |
| } | |
| if ($this->requiredData['review']) { | |
| $this->column[] = 'IFNULL(b.cnt, 0) AS reviewCount'; | |
| $this->column[] = 'IFNULL(b.mcnt, 0) AS reviewCountMobile'; | |
| } else { | |
| $this->column[] = '0 AS reviewCount'; | |
| $this->column[] = '0 AS reviewCountMobile'; | |
| } | |
| if ($this->requiredData['order']) { | |
| $this->column[] = 'IFNULL(o.cnt, 0) AS orderCount'; | |
| $this->column[] = 'IFNULL(o.price, 0) AS orderPrice'; | |
| $this->column[] = 'IFNULL(o.mcnt, 0) AS orderCountMobile'; | |
| $this->column[] = 'IFNULL(o.mprice, 0) AS orderPriceMobile'; | |
| } else { | |
| $this->column[] = '0 AS orderCount'; | |
| $this->column[] = '0 AS orderPrice'; | |
| $this->column[] = '0 AS orderCountMobile'; | |
| $this->column[] = '0 AS orderPriceMobile'; | |
| } | |
| } | |
| /** | |
| $column = 'IFNULL(' . $column . ', 0)'; | |
| } | |
| } | |
| public function setRequiredData(array $requiredData) | |
| { | |
| $this->requiredData = array_merge($this->requiredData, $requiredData); | |
| } | |
| /* | |
| * 회원등급평가 타겟일자 셋팅 | |
| * | |
| * @param string $targetDateTime 수행일자 | |
| */ | |
| public function setTargetDateTime($targetDateTime = null) | |
| { | |
| $this->targetDateTime = $targetDateTime; | |
| } | |
| public function setTargetMembers(array $target = []) | |
| { | |
| $this->targetMembers = $target; | |
| } | |
| public function getEvaluatedMemberSnapshots() | |
| { | |
| return $this->evaluatedMembers; | |
| } | |
| public function removeEvaluatedMemberSnapshots(array $memNos) | |
| { | |
| foreach ($memNos as $memNo) { | |
| unset($this->evaluatedMembers[$memNo]); | |
| } | |
| } | |
| /* | |
| * 타겟일자기준 회원등급평가 완료대상 제외 where 조건 | |
| * | |
| * @return string | |
| */ | |
| public function whereExcludeCompleteMember() | |
| { | |
| $from = $this->db->escape("{$this->targetDateTime} 00:00:00"); | |
| return "(m.autoGroupAppraisalDt IS NULL OR m.autoGroupAppraisalDt < '{$from}')"; | |
| } | |
| } | |
변경 전GroupDomain.php
| private $managerNo; | |
| private $regDt; | |
| private $modDt; | |
| function __construct(array $arr = null) | |
| { | |
| /** | |
| * 객체에 설정된 추가할인적용제외/중복할인적용에 대한 화면에 보여질 정보를 데이터베이스 조회를 통해 설정하는 함수 | |
| */ | |
| public function setGroupDcData() | |
| { | |
| $this->toStrip('dcExOption')->toJsonDecode('dcExOption', true); | |
| $this->toStrip('dcExScm')->toJsonDecode('dcExScm', true); | |
| $this->toStrip('dcExCategory')->toJsonDecode('dcExCategory', true); | |
| public function toStrip($key = null) | |
| { | |
| $this->$key = StringUtils::htmlSpecialCharsStripSlashes($this->$key); | |
| return $this; | |
| } | |
변경 후GroupDomain.php
| private $managerNo; | |
| private $regDt; | |
| private $modDt; | |
| /** @var bool setGroupDcData() 중복 실행 방지 플래그 */ | |
| private $isGroupDcDataSet = false; | |
| function __construct(array $arr = null) | |
| { | |
| /** | |
| * 객체에 설정된 추가할인적용제외/중복할인적용에 대한 화면에 보여질 정보를 데이터베이스 조회를 통해 설정하는 함수 | |
| * | |
| * 조회 결과를 원본 필드에 덮어쓰므로 두 번 호출하면 값이 깨진다. 인스턴스 재사용 시 최초 1회만 수행한다. | |
| */ | |
| public function setGroupDcData() | |
| { | |
| if ($this->isGroupDcDataSet) { | |
| return; | |
| } | |
| $this->isGroupDcDataSet = true; | |
| $this->toStrip('dcExOption')->toJsonDecode('dcExOption', true); | |
| $this->toStrip('dcExScm')->toJsonDecode('dcExScm', true); | |
| $this->toStrip('dcExCategory')->toJsonDecode('dcExCategory', true); | |
| public function toStrip($key = null) | |
| { | |
| // 캐시된 인스턴스를 회원 수만큼 재사용해도 멱등하게 동작한다. | |
| if (is_string($this->$key)) { | |
| $this->$key = StringUtils::htmlSpecialCharsStripSlashes($this->$key); | |
| } | |
| return $this; | |
| } | |
변경 전History.php
| $before = $session->get(Member::SESSION_MODIFY_MEMBER_INFO, null); | |
| $after = $this->db->getData(DB_MEMBER, $this->memNo, 'memNo'); | |
| MemberUtil::combineMemberData($before); | |
| MemberUtil::combineMemberData($after); | |
변경 후History.php
| $before = $session->get(Member::SESSION_MODIFY_MEMBER_INFO, null); | |
| $after = $this->db->getData(DB_MEMBER, $this->memNo, 'memNo'); | |
| // 자동 등급평가 등 세션 미세팅 경로에서 null 이 들어올 수 있음. | |
| // combineMemberData → ArrayUtils::unsetDiff(array $keys) 가 strict 타입이라 TypeError 발생 → 빈 배열로 보정. | |
| if (!is_array($before)) { | |
| $before = []; | |
| } | |
| if (!is_array($after)) { | |
| $after = []; | |
| } | |
| MemberUtil::combineMemberData($before); | |
| MemberUtil::combineMemberData($after); | |
변경 전MemberGroupPsController.php
| $appraisal = \App::load('\\Component\\Member\\Group\\Appraisal'); | |
| $appraisal->setRemoteAddress(Request::getRemoteAddress()); | |
| ini_set('max_execution_time', 0); | |
| $appraisal->appraisalGroupBySearch(); | |
| $appraisal->appraisalMailSend(); | |
| if($appraisal->policy['couponConditionComplete'] == 'y' && $appraisal->policy['couponConditionCompleteChange'] != 'y') { | |
변경 후MemberGroupPsController.php
| $appraisal = \App::load('\\Component\\Member\\Group\\Appraisal'); | |
| $appraisal->setRemoteAddress(Request::getRemoteAddress()); | |
| ini_set('max_execution_time', 0); | |
| if (!method_exists($appraisal, 'setTargetDateTime')) { | |
| throw new \Exception('Appraisal 구버전 감지: setTargetDateTime 메서드 누락. Appraisal.php 를 코어와 동기화해주세요.'); | |
| } | |
| $appraisal->setTargetDateTime(); | |
| $appraisal->appraisalGroupBySearch(); | |
| $appraisal->appraisalMailSend(); | |
| if($appraisal->policy['couponConditionComplete'] == 'y' && $appraisal->policy['couponConditionCompleteChange'] != 'y') { | |
변경 전crm_recipe_send.php
| <h3 class="ncua-help-manual"><?= gd_htmlspecialchars($recipeName ?? '레시피') ?></h3> | |
| <div class="ncua-page-header__actions"> | |
| <button id="closeCrmRecipe" type="button" class="ncua-btn ncua-btn--sm ncua-btn--secondary-gray">닫기</button> | |
| <button id="previewCrmRecipe" type="button" class="ncua-btn ncua-btn--sm ncua-btn--primary">발송</button> | |
| </div> | |
| </header> | |
변경 후crm_recipe_send.php
| <h3 class="ncua-help-manual"><?= gd_htmlspecialchars($recipeName ?? '레시피') ?></h3> | |
| <div class="ncua-page-header__actions"> | |
| <button id="closeCrmRecipe" type="button" class="ncua-btn ncua-btn--sm ncua-btn--secondary-gray">닫기</button> | |
| <button id="previewCrmRecipe" type="button" class="ncua-btn ncua-btn--sm ncua-btn--primary">반복발송</button> | |
| </div> | |
| </header> | |
변경 전layer_recipe_send_time_setting.php
| <h4 class="ncua-card__title"> | |
| 발송 설정 | |
| </h4> | |
| </header> | |
| <section class="ncua-card__body"> | |
| <div class="send-time-setting-content"> | |
변경 후layer_recipe_send_time_setting.php
| <h4 class="ncua-card__title"> | |
| 발송 설정 | |
| </h4> | |
| <p class="send-time-setting-desc">발송 기간과 주기를 설정해 메시지를 반복 발송해보세요.</p> | |
| </header> | |
| <section class="ncua-card__body"> | |
| <div class="send-time-setting-content"> | |