19 "operation" => array(
"filter" => FILTER_SANITIZE_STRING),
20 "promos" => array(
"filter" => FILTER_SANITIZE_STRING),
21 "accounts" => array(
"filter" => FILTER_SANITIZE_STRING)
23 HCU_ImportVars($admVars,
"USERFLAGS", $admOk);
25 $pOperation = isset($admVars[
'USERFLAGS'][
'operation']) ? $admVars[
'USERFLAGS'][
'operation'] :
null;
26 $pPromo = isset($admVars[
'USERFLAGS'][
'promos']) ? $admVars[
'USERFLAGS'][
'promos'] :
null;
27 $pAccounts = isset($admVars[
'USERFLAGS'][
'accounts']) ? $admVars[
'USERFLAGS'][
'accounts'] :
null;
32 switch ($pOperation) {
34 PrintPromoListContent();
35 PromoRead($SYSENV, $dbh, $Cu);
38 header(
'Content-type: application/json');
40 $rPromoList = PromoRead($SYSENV, $dbh, $Cu);
41 if (HCU_array_key_exists(
"error", $rPromoList)) {
42 $aryResult[
'error'] = $rPromoList[
'error'];
44 $aryResult[
'data'][
'promos'] = $rPromoList[
'promos'];
47 PromoReply($aryResult, $aryReply, $pOperation);
50 header(
'Content-type: application/json');
52 $rPromoReset = PromoReset($SYSENV, $dbh, $Cu, $pPromo);
53 if (HCU_array_key_exists(
"error", $rPromoReset)) {
54 $aryResult[
'error'] = $rPromoReset[
'error'];
56 $aryResult[
'info'] = $rPromoReset[
'info'];
59 $rPromoList = PromoRead($SYSENV, $dbh, $Cu);
60 if (HCU_array_key_exists(
"error", $rPromoList)) {
61 $aryResult[
'error'] = $rPromoList[
'error'];
63 $aryResult[
'data'][
'promos'] = $rPromoList[
'promos'];
66 PromoReply($aryResult, $aryReply, $pOperation);
69 header(
'Content-type: application/json');
71 $rAccountSet = PromoSuppress($SYSENV, $dbh, $Cu, $pAccounts);
72 if (HCU_array_key_exists(
"error", $rAccountSet)) {
73 $aryResult[
'error'] = $rAccountSet[
'error'];
75 $aryResult[
'info'] = $rAccountSet[
'info'];
78 $rPromoList = PromoRead($SYSENV, $dbh, $Cu);
79 if (HCU_array_key_exists(
"error", $rPromoList)) {
80 $aryResult[
'error'] = $rPromoList[
'error'];
82 $aryResult[
'data'][
'promos'] = $rPromoList[
'promos'];
85 PromoReply($aryResult, $aryReply, $pOperation);
88 throw new Exception(
"Unknown server request: " . $pOperation);
92 }
catch (Exception $e) {
93 $aryReply[
'errors'][] = $e->getMessage();
94 $aryResult[
'data'] = array();
95 $aryResult[
'info'] = array();
97 PromoReply($aryResult, $aryReply, $pOperation);
104 function GetTypeMap() {
105 return array(
"N" =>
"None",
"T" =>
"Terms of Use",
"D" =>
"Notice/Disclaimer",
"A" =>
"Promo/All Members",
"E" =>
"Promo/No eStatements",
"P" =>
"Promo/Persistent");
118 function PromoReply($pResult, $pReply, $pOperation) {
119 $pReply[
'operation'] = $pOperation;
120 if (isset($pResult[
'error']) && count($pResult[
'error'])) $pReply[
'error'] = $pResult[
'error'];
121 if (isset($pResult[
'data']) && count($pResult[
'data'])) $pReply[
'data'] = $pResult[
'data'];
122 if (isset($pResult[
'info']) && count($pResult[
'info'])) $pReply[
'info'] = $pResult[
'info'];
124 print HCU_JsonEncode(array(
"Results" => $pReply));
138 function PromoRead($pEnv, $pDbh, $pCu) {
139 $sqlReturn = array();
143 d.docstitle AS dtitle, 145 d.docsresponsetype AS dresponse";
149 WHERE r.docsid = d.docsid 151 AND r.responseon IS NOT NULL";
153 SELECT $sqlColumns, ($sqlSub) AS dcount 155 LEFT JOIN cucmsfrags f 156 ON f.docsid = d.docsid 158 WHERE d.docsresponsetype IN ('D', 'A', 'E', 'P', 'T') 159 ORDER BY array_position(array['D', 'A', 'E', 'P', 'T'], d.docsresponsetype::text), d.docsdesc";
161 $sqlSelectRs = db_query($sqlSelect, $pDbh);
163 $pEnv[
'logger']->error(db_last_error());
164 $sqlReturn[
'error'][] =
"Failed to read promos list.";
168 $promos = db_fetch_all($sqlSelectRs);
169 $promos = $promos ===
false ? array() : $promos;
171 for($i = 0, $count = count($promos); $i != $count; $i++) {
172 $type = trim($promos[$i][
"dresponse"]);
173 $typeText = HCU_array_key_value($type, GetTypeMap());
174 $typeText = $typeText ===
false ?
"" : $typeText;
175 $promos[$i][
"typeText"] = $typeText;
178 $sqlReturn[
'promos'] = $promos;
194 function PromoReset($pEnv, $pDbh, $pCu, $pPromo) {
198 $promos = html_entity_decode($pPromo, ENT_QUOTES);
199 $promos = str_replace(array(
'[',
']'),
"", $promos);
200 $promos = str_replace(
'"',
"'", $promos);
202 $sqlReturn = array();
205 SET responseon = NULL 207 AND docsid IN ($promos)";
208 $sqlUpdateRs = db_query($sqlUpdate, $pDbh);
210 $pEnv[
'logger']->error(db_last_error());
211 $sqlReturn[
'error'][] =
"Failed to reset selected promos.";
215 $sqlReturn[
'info'][] =
"Reset was successful.";
216 $sqlReturn[
'promos'] = db_fetch_all($sqlUpdateRs);
232 function PromoSuppress($pEnv, $pDbh, $pCu, $pAccounts) {
236 $accountsList = html_entity_decode($pAccounts, ENT_QUOTES);
237 $accountsList = HCU_JsonDecode($accountsList);
238 foreach ($accountsList as $key => $value) {
239 $accountsList[$key] = trim($value);
241 $accounts = HCU_JsonEncode($accountsList);
242 $accounts = str_replace(array(
'[',
']'),
"", $accounts);
243 $accounts = str_replace(
'"',
"'", $accounts);
249 $sqlReturn = array();
252 $sql =
"select distinct u.user_id, uc.accountnumber from {$pCu}user u 253 inner join {$pCu}useraccounts uc on u.user_id = uc.user_id 254 where uc.accountnumber in ($accounts)";
255 $sqlRs = db_query($sql, $pDbh);
257 $pEnv[
'logger']->error(db_last_error());
258 $sqlReturn[
'error'][] =
"Failed to read user accounts.";
261 $users = db_fetch_all($sqlRs);
262 foreach ($accountsList as $key => $value) {
263 $acct = trim($value);
267 while ($row = db_fetch_assoc($sqlRs, $i)) {
268 $prim = trim($row[
'accountnumber']);
269 if ($prim == $acct) {
277 $sqlReturn[
"error"][] =
"Account number: $acct does not exist";
281 if (HCU_array_key_exists(
"error", $sqlReturn)) {
291 LEFT JOIN cucmsfrags f 292 ON f.docsid = d.docsid 294 WHERE d.docsresponsetype = 'P'";
295 $sqlRs = db_query($sql, $pDbh);
297 $pEnv[
'logger']->error(db_last_error());
298 $sqlReturn[
'error'][] =
"Failed to read promos list.";
301 $docs = db_fetch_all($sqlRs);
302 if (db_num_rows($sqlRs) == 0) {
303 $sqlReturn[
'error'][] =
"No persistent promos currently exist.";
308 $cu = prep_save($pCu);
313 $sqlSuccess = array();
314 for ($i = 0; $i < count($users); $i++) {
315 $userId = intval($users[$i][
'user_id']);
316 $userAccount = prep_save($users[$i][
'accountnumber']);
319 for ($j = 0; $j < count($docs); $j++) {
320 $docId = intval($docs[$j][
'docsid']);
323 docsid, cu, accountnumber, responseon, user_id";
325 $docId, '{$cu}', '$userAccount', current_date, $userId";
327 INSERT INTO cucmsresponse 333 WHERE r.docsid = $docId 334 AND r.accountnumber = '$userAccount' 335 AND r.cu = '{$cu}'))";
337 $sqlRs = db_query($sql, $pDbh);
339 $pEnv[
'logger']->error(db_last_error());
343 if (db_affected_rows($sqlRs) == 0) {
346 SET responseon = current_date 347 WHERE docsid = $docId 348 AND user_id = $userId 350 $sqlRs = db_query($sql, $pDbh);
352 $pEnv[
'logger']->error(db_last_error());
359 $sqlReturn[
'error'][] =
"User account: $userAccount could not be excluded.";
361 if (!in_array($userAccount, $sqlSuccess)) {
362 $sqlSuccess[] = $userAccount;
363 $sqlReturn[
'info'][] =
"User account: $userAccount excluded successfully.";
379 <?php
function PrintPromoListContent() { ?>
380 <style type=
"text/css">
382 .k-grid tbody tr input[type=
"checkbox"],
383 .k-grid thead tr input[type=
"checkbox"] {
388 <div
class=
"col-sm-12">
389 <div
class=
"well well-sm col-sm-12">
390 <h2>Reset Pop-Ups and Promos</h2>
392 <div
class=
"hcu-secondary">
393 <div
class=
"vsgSecondary">
394 <p>By
default, Pop-up messages and
User-Dismissible Login Promos are shown to all users. Users may dismiss the message or promo by specifying
"Don't Tell Me Again".</p>
395 <p>When you reset these flags, all users will see the related message or promo again, even
if they previously checked
"Don't Tell Me Again".</p>
397 <div
class=
"small vsgSecondary">
398 <span>Disabled rows indicate a pop-up message or promo that is not currently dismissed
for any users.</span>
402 <div
class=
"" id=
"rfTable"></div>
403 <div
class=
"" style=
"margin-top: 7.5px; margin-bottom: 7.5px;">
404 <button
class=
"k-button k-primary" id=
"rfBtnReset">Reset Flags</button>
408 <div
class=
"well well-sm col-sm-12">
409 <h3>Exclude From CU-Dismissible Login Promo</h3>
410 <div
class=
"hcu-secondary">
411 <div
class=
"vsgSecondary">
412 <p>By
default, the CU-Dismissible Login Promo is shown to all users. If you wish to exclude certain users from
this promo, use the box below to enter their accounts. </p>
413 <p>Insert the account numbers into
this entry field, separated by a space or
new line. <br>If the record does not exist or cannot be updated, an error will be displayed.</p>
418 <textarea
class=
"k-textbox hcu-all-100" id=
"rfExclude" rows=
"3"></textarea>
420 <div
class=
"" style=
"margin-top: 7.5px; margin-bottom: 7.5px;">
421 <button
class=
"k-button k-primary" id=
"rfBtnSet">Set Flags</button>
427 <script type=
"text/javascript">
428 <?php getShowWaitFunctions(); ?>
429 var rfDataSource =
null;
431 var rfTableData =
null;
432 var rfTooltip =
null;
434 var InitDataSources =
function() {
436 rfDataSource =
new kendo.data.DataSource({
441 contentType:
"application/x-www-form-urlencoded",
449 requestStart:
function(request) {
452 requestEnd:
function(response) {
455 if (response.hasOwnProperty(
"response")) {
456 if (response.response.hasOwnProperty(
"Results")) {
457 var results = response.response.Results;
459 if (results.hasOwnProperty(
"error")) {
460 $.homecuValidator.homecuResetMessage =
true;
461 $.homecuValidator.displayMessage(results.error, $.homecuValidator.settings.statusError);
462 }
else if (results.hasOwnProperty(
"info")) {
463 $.homecuValidator.homecuResetMessage =
true;
464 $.homecuValidator.displayMessage(results.info, $.homecuValidator.settings.statusSuccess);
467 $.homecuValidator.displayMessage(
"Error Parsing Server", $.homecuValidator.settings.statusError);
470 $.homecuValidator.displayMessage(
"Error Parsing Server", $.homecuValidator.settings.statusError);
474 parse:
function(response) {
476 var resultData =
null;
477 var resultOperation =
null;
479 if (response.hasOwnProperty(
"Results")) {
480 results = response.Results;
481 resultData = results.data;
482 resultOperation = results.operation;
485 if (results.hasOwnProperty(
"error")) {
490 if (resultData == undefined || resultData ==
null) {
495 rfTableData = resultData.promos;
496 rfTable.dataSource.data(rfTableData);
504 var InitDataViews =
function() {
505 rfTable = $(
"#rfTable").kendoGrid({
512 template:
"<span class=\"hcu-secondary\"><span class=\"vsgSecondary\">No Records Found</span></span>" 515 { title:
"", width:
"35px",
516 template:
"<input type=\"checkbox\" id=\"#=did#\" name=\"resetCheck\">",
517 headerTemplate:
"<input type=\"checkbox\" id=\"0\" name=\"resetCheck\">" },
518 { field:
"ddesc", title:
"Description",
519 attributes: {
"class":
"showEllipsis" } },
520 { field:
"typeText", title:
"Type" , width:
"200px", attributes: {
"class":
"hidden-xs" }, headerAttributes: {
"class":
"hidden-xs" } },
521 { field:
"dcount", title:
"User Count", width:
"100px" }
523 change:
function(e) {
524 var row = this.select();
525 var rowBox = row.find(
"input[type=\"checkbox\"]");
526 rowBox.trigger(
"click");
528 $(this.select()).removeClass(
'k-state-selected');
530 dataBound:
function(e) {
533 $(
"#rfTable colgroup").each(
function() {
534 $(
this).find(
"col:eq(2)").addClass(
"hidden-xs");
538 $(
"#rfTable tbody tr").each(
function() {
539 var dataItem = rfTable.dataItem(
this);
540 var count = dataItem.dcount;
542 $(
this).addClass(
"vsgDisabled");
543 $(
this).find(
"input[type=\"checkbox\"]").prop(
"disabled",
true);
548 $(
"#rfTable input[id=\"0\"]").prop(
"checked",
false);
551 $(
"#rfTable input[type=\"checkbox\"]").off();
552 $(
"#rfTable input[type=\"checkbox\"]").on(
"click",
function() {
555 var
id = $(
this).attr(
"id");
556 var checked = $(
this).prop(
"checked");
560 $(
"#rfTable input[id!=\"0\"]:not(:disabled)").prop(
"checked", checked);
562 var disabled = $(
"#rfTable input[id!=\"0\"]:disabled");
563 var enabled = $(
"#rfTable input[id!=\"0\"]:not(disabled)");
564 var checked = $(
"#rfTable input[id!=\"0\"]:checked:not(disabled)");
569 if (checked.length == rfTableData.length - disabled.length) {
570 $(
"#rfTable input[id=\"0\"]").prop(
"checked",
true);
572 $(
"#rfTable input[id=\"0\"]").prop(
"checked",
false);
577 }).data(
"kendoGrid");
579 $(
"#rfBtnReset").on(
"click",
function() {
580 var boxes = $(
"#rfTable input:checked[id!=\"0\"]");
581 var count = boxes.length;
582 var grid = $(
"#rfTable").data(
"kendoGrid");
583 var tosDisclosures = 0;
584 var hasSignupDisclosure =
false;
588 boxes.each(
function() {
589 var row = $(
this).closest(
"tr");
590 var dataItem = grid.dataItem($(row));
591 ids.push(dataItem.did);
592 if (dataItem.dresponse ==
"T") {
595 hasSignupDisclosure = hasSignupDisclosure || dataItem.dname ==
"signupDisclosure";
598 if (tosDisclosures > 0 || hasSignupDisclosure) {
602 if (tosDisclosures > 0) {
603 var thisOrThese = count == 1 ?
"this" :
"these";
604 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
605 message +=
"Be aware that resetting " + thisOrThese +
" Terms of Use will erase all previous dates of acceptance by users.";
606 message +=
"</div></div>";
607 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
608 message +=
"Before resetting " + thisOrThese +
" Terms of Use, HomeCU recommends that you download and retain the current \"Terms Accepted\" report in your admin site under ";
609 message +=
"<a href='main.prg?ft=41&report=termsAccepted'>Reports > User Settings Reports</a>.";
610 message +=
"</div></div>";
613 if (hasSignupDisclosure) {
614 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'> </div></div>";
615 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
616 message +=
"Resetting the <b>Digital Banking Disclosure</b> will not show this disclosure to the user on their next login. ";
617 message +=
"To show users an updated disclosure we recommend using a marketing message with a link to the new disclosure.";
618 message +=
"</div></div>";
619 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
620 message +=
"To set up a marketing message in your admin site, go to " 621 message +=
"<a href='main.prg?ft=37&page=edit'>Member Communications > Marketing Messages > New Marketing Message</a>.";
622 message +=
"</div></div>";
623 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
624 message +=
"If you have questions on setting on a marketing message, please contact HomeCU support for assistance.";
625 message +=
"</div></div>";
628 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'> </div></div>";
629 message +=
"<div class='row'><div class='col-xs-12 hcuSpacer'>";
630 message +=
"Do you want to continue?";
631 message +=
"</div></div>";
633 var tosDialog = $(
"#tosDialog").data(
"kendoDialog");
635 tosDialog = $(
"<div id='tosDialog'></div>").appendTo(
"body").kendoDialog({
640 {text:
"Confirm Reset", primary:
true, action:
function() {
641 var ids = $(
"#tosDialog").data(
"ids");
642 rfDataSource.transport.options.read.type =
"POST";
644 operation:
"promoReset",
645 promos: JSON.stringify(ids)
650 }).data(
"kendoDialog");
653 $(
"#tosDialog").data(
"ids", ids);
654 tosDialog.content(message).open();
656 rfDataSource.transport.options.read.type =
"POST";
658 operation:
"promoReset",
659 promos: JSON.stringify(ids)
666 $(
"#rfBtnSet").on(
"click",
function() {
667 var input = $(
"#rfExclude");
668 var text = input.val();
671 if (text.trim().length > 0) {
672 var accts = text.split(/\s+/);
674 rfDataSource.transport.options.read.type =
"POST";
676 operation:
"promoSuppress",
677 accounts: JSON.stringify(accts)
683 jQuery.extend(jQuery.expr[
':'], {
684 overflown: function (el) {
685 return el.offsetHeight < el.scrollHeight || el.offsetWidth < el.scrollWidth;
689 rfTooltip = homecuTooltip.defaults;
690 rfTooltip.filter =
".showEllipsis:overflown";
691 rfTooltip.content =
function(e) {
692 return $(e.target).text().trim();
694 $(
"#rfTable").kendoTooltip(rfTooltip);
697 $(document).ready(
function() {
701 rfDataSource.transport.options.read.type =
"POST";
703 operation:
"promoRead"