20 require_once(
"$admLibrary/aGroupSupport.i");
21 require_once(
"$sharedLibrary/sFeatureMnu.i");
26 "operation" => array(
"filter" => FILTER_SANITIZE_STRING),
27 "payload" => array(
"filter" => FILTER_SANITIZE_STRING),
28 "gSettings" => array(
"filter" => FILTER_SANITIZE_STRING),
31 HCU_ImportVars($admVars,
"GROUP_SETTINGS", $admOk);
33 $sOperation = isset($admVars[
"GROUP_SETTINGS"][
"operation"]) ? $admVars[
"GROUP_SETTINGS"][
"operation"] :
null;
34 $sPayload = isset($admVars[
"GROUP_SETTINGS"][
"payload"]) ? $admVars[
"GROUP_SETTINGS"][
"payload"] :
null;
35 $sSettings = isset($admVars[
"GROUP_SETTINGS"][
"gSettings"]) ? $admVars[
"GROUP_SETTINGS"][
"gSettings"] :
null;
41 GroupDecrypt($SYSENV, $Cu, $sPayload) :
45 $sContext = $sPayload ?
46 GroupContext($SYSENV, $Cu, $sGroup[
'group']) :
47 GroupContext($SYSENV, $Cu);
52 switch ($sOperation) {
56 $featureList = FetchMenuFeatureList( array(
"dbh" => $dbh), array(
"Cu"=>$Cu) );
57 $featureMenuHasACH =
false;
58 if (in_array(
"ACHPMT", $featureList[
'data']) || in_array(
"ACHCOL", $featureList[
'data'])) {
59 $featureMenuHasACH =
true;
61 PrintGroupSettings($featureMenuHasACH);
63 case "groupReadSettings":
64 header(
'Content-type: application/json');
65 $gProfiles = GroupReadProfiles($SYSENV, $dbh, $sContext);
66 $gSettings = GroupReadSettings($SYSENV, $dbh, $sContext);
68 $aryResult[
'data'][
'settings'] = $gSettings[
'settings'];
69 $aryResult[
'data'][
'profiles'] = $gProfiles[
'profiles'];
70 GroupReply($aryResult, $aryReply, $sOperation);
72 case "groupUpdateSettings":
73 header(
'Content-type: application/json');
74 $gValidate = GroupValidateSettings($SYSENV, $sSettings);
78 if (HCU_array_key_exists(
"info", $gValidate)) {
79 $gInfo = GroupUpdateInfo($SYSENV, $dbh, $sContext, $gValidate[
'info']);
81 $sGroup[
'group'][
'g_name'] = $gInfo[
'info'][
'group_name'];
83 $aryResult[
'info'][] = $gInfo[
'message'];
87 if (HCU_array_key_exists(
"profile", $gValidate)) {
88 $gProfile = GroupUpdateProfile($SYSENV, $dbh, $sContext, $gValidate[
'profile']);
90 $sGroup[
'group'][
'g_profile'] = $gProfile[
'profile'][
'name'];
91 $sGroup[
'group'][
'p_id'] = $gProfile[
'profile'][
'id'];
93 $aryResult[
'info'][] = $gProfile[
'message'];
98 $sContext[
'g_name'] = $sGroup[
'group'][
'g_name'];
99 $sContext[
'p_id'] = $sGroup[
'group'][
'p_id'];
100 $sGroup = GroupSelect($SYSENV, $dbh, $sContext);
101 $sEncrypt = GroupEncrypt($SYSENV, $Cu, $sGroup);
104 $aryResult[
'data'][
'group'] = $sGroup;
105 $aryResult[
'data'][
'encrypt'] = $sEncrypt;
106 GroupReply($aryResult, $aryReply, $sOperation);
109 throw new Exception(
"Unknown server request: " . $sOperation);
113 }
catch (Exception $e) {
114 $aryReply[
'errors'][] = $e->getMessage();
115 $aryResult[
'data'] = array();
116 $aryResult[
'info'] = array();
118 GroupReply($aryResult, $aryReply, $sOperation);
133 function GroupValidateSettings($pEnv, $pSettings) {
134 $gSettings = html_entity_decode($pSettings, ENT_QUOTES);
135 $gSettings = json_decode($gSettings,
true);
136 $vSettings = array();
138 if (HCU_array_key_exists(
"gName", $gSettings)) {
139 $vSettings[
'info'][
'name'] = prep_save($gSettings[
'gName'], 50);
142 if (HCU_array_key_exists(
"gTaxID", $gSettings)) {
143 $vSettings[
'info'][
'taxid'] = prep_save($gSettings[
'gTaxID'], 10);
146 if (HCU_array_key_exists(
"gProfile", $gSettings)) {
147 $vSettings[
'profile'] = prep_save($gSettings[
'gProfile'], 255);
167 function GroupUpdateProfile($pEnv, $pDbh, $pContext, $pProfile) {
168 if ($pProfile ==
null || $pProfile ==
"") {
return array(); }
170 $gId = $pContext[
'g_id'];
171 $pId = $pContext[
'p_id'];
172 $cuTable = $pContext[
'cu_table'];
173 $cuCode = $pContext[
'cu_code'];
175 $sqlReturn = array();
177 $pDesc = prep_save($pProfile, 255);
178 $sqlSelect =
"SELECT profile_id AS p_id 180 WHERE description = '$pDesc' 183 $sqlSelectRs = db_query($sqlSelect, $pDbh);
184 $sqlSelectRow = db_fetch_assoc($sqlSelectRs);
185 $pId = intval($sqlSelectRow[
'p_id']);
188 $sqlUpdate =
"UPDATE {$cuTable}group 189 SET profile_id = $pId 190 WHERE group_id = $gId";
191 $sqlUpdateRs = db_query($sqlUpdate, $pDbh);
193 $pEnv[
'logger']->error(db_last_error());
194 throw new Exception(
"Failed to update group profile.");
198 $sqlDelete =
"DELETE FROM {$cuTable}grouprights 199 WHERE group_id = $gId";
200 $sqlDeleteRs = db_query($sqlDelete, $pDbh);
202 $pEnv[
'logger']->error(db_last_error());
203 throw new Exception(
"Failed to update group rights.");
207 $sqlDelete =
"DELETE FROM {$cuTable}userrights ur 208 USING {$cuTable}user u 209 WHERE ur.user_id = u.user_id 210 AND u.group_id = $gId 211 AND ur.feature_code NOT IN 212 (SELECT pr.feature_code FROM cu_profilerights pr WHERE pr.profile_id = $pId)";
213 $sqlDeleteRs = db_query($sqlDelete, $pDbh);
214 $sqlDeleteRs = db_query($sqlDelete, $pDbh);
216 $pEnv[
'logger']->error(db_last_error());
217 throw new Exception(
"Failed to update user rights rights.");
222 f.feature_code AS f_code, 223 f.description AS f_desc, 224 u.user_name AS u_user";
226 ur.amount_per_transaction != pr.amount_per_transaction 227 OR ur.amount_per_account_per_day != pr.amount_per_account_per_day 228 OR ur.amount_per_day != pr.amount_per_day 229 OR ur.amount_per_month != pr.amount_per_month 230 OR ur.count_per_account_per_day != pr.count_per_account_per_day 231 OR ur.count_per_day != pr.count_per_day 232 OR ur.count_per_month != pr.count_per_month 233 OR ur.confirm_required != pr.confirm_required";
234 $sqlSelect =
"SELECT $sqlColumns 235 FROM {$cuTable}userrights ur 236 INNER JOIN {$cuTable}user u ON u.user_id = ur.user_id 237 INNER JOIN {$cuTable}group g ON g.group_id = u.group_id 238 INNER JOIN cu_feature f ON f.feature_code = ur.feature_code 239 FULL OUTER JOIN cu_profilerights pr ON pr.feature_code = ur.feature_code 240 WHERE g.group_id = $gId 241 AND pr.profile_id = $pId 243 $sqlSelectRs = db_query($sqlSelect, $pDbh);
245 $pEnv[
'logger']->error(db_last_error());
246 throw new Exception(
"Failed to read user rights.");
249 $sqlReturn[
'message'] =
"Group profile has been updated successfully.";
250 $sqlReturn[
'profile'] = array(
"name"=> $pDesc,
"id"=>$pId);
251 if (db_num_rows($sqlSelectRs) > 0) {
252 $sqlReturn[
'message'] .=
"<br>  The following users may have feature limits that differ from the new profile.";
254 while ($row = db_fetch_assoc($sqlSelectRs)) {
255 $sqlReturn[
'message'] .=
"<br>  — User: " . $row[
'u_user'] .
" Feature: " . $row[
'f_desc'];
273 function GroupUpdateInfo($pEnv, $pDbh, $pContext, $pInfo) {
274 $gId = $pContext[
'g_id'];
275 $pId = $pContext[
'p_id'];
276 $cuTable = $pContext[
'cu_table'];
277 $cuCode = $pContext[
'cu_code'];
279 $sqlReturn = array();
280 $sqlColumns = array();
281 $sqlValues = array();
284 if (HCU_array_key_exists(
"name", $pInfo)) {
285 $sqlColumns[] =
"group_name";
286 $sqlValues[] =
"'{$pInfo['name']}'";
289 if (HCU_array_key_exists(
"taxid", $pInfo)) {
290 $sqlColumns[] =
"tax_id";
291 $sqlValues[] =
"'{$pInfo['taxid']}'";
294 $sqlColumns = implode(
",", $sqlColumns);
295 $sqlValues = implode(
",", $sqlValues);
297 $sqlUpdate =
"UPDATE {$cuTable}group 298 SET ($sqlColumns) = ($sqlValues) 299 WHERE group_id = $gId 301 RETURNING group_name, tax_id";
303 $sqlUpdateRs = db_query($sqlUpdate, $pDbh);
305 $pEnv[
'logger']->error(db_last_error());
306 throw new Exception(
"Failed to update group information.");
309 $sqlReturn[
'info'] = db_fetch_all($sqlUpdateRs)[0];
310 $sqlReturn[
'message'] =
"Group information has been updated successfully.";
324 function GroupReadSettings($pEnv, $pDbh, $pContext) {
325 $gId = $pContext[
'g_id'];
326 $pId = $pContext[
'p_id'];
327 $cuTable = $pContext[
'cu_table'];
328 $cuCode = $pContext[
'cu_code'];
330 $sqlReturn = array();
333 g.group_name AS g_name, 335 p.description AS p_desc";
337 $sqlSelect =
"SELECT $sqlColumns 338 FROM {$cuTable}group g 339 INNER JOIN cu_profile p ON g.profile_id = p.profile_id 340 WHERE g.group_id = $gId 341 AND g.profile_id = $pId";
343 $sqlSelectRs = db_query($sqlSelect, $pDbh);
345 $pEnv[
'logger']->error(db_last_error());
346 throw new Exception(
"Failed to read group information.");
349 $sqlReturn[
'settings'] = db_fetch_all($sqlSelectRs)[0];
363 function GroupReadProfiles($pEnv, $pDbh, $pContext) {
364 $cuCode = $pContext[
'cu_code'];
366 $sqlReturn = array();
368 description AS p_desc";
370 $sqlSelect =
"SELECT $sqlColumn 373 ORDER BY description ASC";
375 $sqlSelectRs = db_query($sqlSelect, $pDbh);
377 $pEnv[
'logger']->error(db_last_error());
378 throw new Exception(
"Failed to read profiles.");
381 $sqlReturn[
'profiles'] = db_fetch_all($sqlSelectRs);
392 function PrintGroupSettings($featureMenuHasACH) { ?>
393 <div
id=
"gsSettings">
394 <div
id=
"status"></div>
395 <div
class=
"col-sm-12"> </div>
396 <div
class=
"well well-sm col-sm-12">
398 <div
class=
"col-sm-5">
399 <label
for=
"gsInpProfile">
401 <span
class=
"fa fa-asterisk" style=
"color: #f0ad4e;" 402 data-bind=
"visible: source.e_dirty"></span>
405 <div
class=
"col-sm-7">
406 <input
class=
"hcu-all-100" id=
"gsInpProfile" 407 data-role=
"dropdownlist" 408 data-value-field=
"o_desc" 409 data-text-field=
"o_desc" 412 value: source.e_profile, 413 events: { change: change }">
418 <div
class=
"col-sm-5">
419 <label
for=
"gsInpGroup">
420 <span>Group Name</span>
421 <span
class=
"fa fa-asterisk" style=
"color: #f0ad4e;" 422 data-bind=
"visible: source.e_dirty"></span>
425 <div
class=
"col-sm-7"><input
class=
"hcu-all-100 k-input k-textbox" id=
"gsInpGroup" name=
"gsInpGroup" 428 value: source.e_group, 429 events: { change: change }" 430 data-required-msg=
"Group name is required" 433 <?php
if ($featureMenuHasACH) : ?>
436 <div
class=
"col-sm-5">
437 <label
for=
"gsInpTaxID">
438 <span>Commercial Tax ID</span>
439 <span
class=
"fa fa-asterisk" style=
"color: #f0ad4e;" 440 data-bind=
"visible: source.e_dirty"></span>
443 <div
class=
"col-sm-7">
444 <input
class=
"hcu-all-100" id=
"gsInpTaxID" name=
"gsInpTaxID" 447 data-homecuCustomMinLen-msg=
"Commercial Tax ID requires 9 characters" 448 data-role=
"numerictextbox" 449 data-spinners=
"false" 452 data-bind=
"value: source.e_taxid, events: {change: change}">
453 <label
for=
"gsInpTaxType1" style=
"margin-top: 2px;">
454 <input
id=
"gsInpTaxType1" type=
"radio" name=
"taxtype" value=
"1" style=
"margin-top: -2px;" 455 data-bind=
"checked: source.e_taxcd, events: {change: change}">
459 <label
for=
"gsInpTaxType9" style=
"margin-top: 2px;">
460 <input
id=
"gsInpTaxType9" type=
"radio" name=
"taxtype" value=
"9" style=
"margin-top: -2px;" 461 data-bind=
"checked: source.e_taxcd, events: {change: change}">
469 <div
class=
"hcu-template">
470 <div
class=
"hcu-edit-buttons k-state-default">
471 <span
class=
"hcu-icon-delete"></span>
472 <a href=
"##" id=
"lnkCancel">Cancel</a>
474 <a href=
"##" id=
"btnUpdate" class=
"k-button k-primary">
475 <i
class=
"fa fa-check fa-lg"></i>
482 <div
class=
"row" id=
"gsDiscard">
483 <div
class=
"col-sm-12">
484 <p>This group
's information has been changed.</p> 485 <p>Do you wish to discard the changes?</p> 527 <script type="text/javascript">
529 var GroupSettings = function() {
530 var gsCardContainer = null;
531 var gsCardWindows = null;
533 var gsPayload = null;
537 var gsDataSource = null;
539 var gsSettings = null;
540 var gsObserve = null;
542 var gsHasCommercial = <?php echo HCU_JsonEncode($featureMenuHasACH); ?>;
544 var ValidateSettings = function() {
545 var source = gsObserve.source;
547 // group profile information
548 var profileLbl = $("label[for=gsInpProfile]");
549 var profileWrn = $(profileLbl.find("span")[1]);
550 var profile_e = null;
551 var profile_o = source.o_profile;
553 if (source.e_profile) {
554 if (typeof source.e_profile == "string") {
555 profile_e = source.e_profile;
557 profile_e = source.e_profile.e_desc;
561 if (profile_e != profile_o) {
567 // group name information
568 var groupLbl = $("label[for=gsInpGroup]");
569 var groupWrn = $(groupLbl.find("span")[1]);
570 var group_e = source.e_group.trim();
571 var group_o = source.o_group.trim();
573 if (group_e != group_o) {
579 // only validatethe tax id fields if the credit union
580 // has access to any ach commercial features.
581 var taxIDChanged = false;
582 if (gsHasCommercial) {
583 // get label and warning fields
584 var taxLbl = $("label[for=gsInpTaxID]");
585 var taxWrn = $(taxLbl.find("span")[1]);
587 // because masked textboxes don't strip the prompt chars, i.e. underscore
589 var taxID_e = source.e_taxid ==
null ?
"" :
"" + source.e_taxid;
590 var taxID_o = source.o_taxid ==
null ?
"" :
"" + source.o_taxid;
592 var taxCD_e = source.e_taxcd;
593 var taxCD_o = source.o_taxcd;
596 (taxID_e != taxID_o) ||
597 (taxCD_e != taxCD_o);
607 if (taxID_e ==
null || taxID_e.length == 0 || taxID_e.length == 9) {
608 $(
"#gsInpTaxID").parent().css(
"border-color",
"#ceced2");
610 $(
"#gsInpTaxID").parent().css(
"border-color",
"#d80000");
615 profile_e != profile_o ||
616 group_e != group_o ||
619 return source.e_dirty;
622 var DataBuildSettings =
function(data) {
624 o_group: data.g_name.trim(),
625 o_profile: data.p_desc.trim(),
626 e_group: data.g_name.trim(),
627 e_profile: data.p_desc.trim(),
633 if (gsHasCommercial) {
634 var taxID = data.g_taxid ==
null ?
"" : data.g_taxid;
642 taxIDType = taxID.length > 0 ? taxID.substring(0, 1) :
"1";
643 taxID = taxID.length > 0 ? taxID.substring(1) : taxID;
645 info.o_taxid = taxID;
646 info.e_taxid = taxID;
647 info.o_taxcd = taxIDType;
648 info.e_taxcd = taxIDType;
651 gsObserve.set(
"source", info);
654 var DataBuildProfiles =
function(data) {
656 for (var i = 0; i < data.length; i++) {
658 o_desc: data[i].p_desc.trim(),
659 e_desc: data[i].p_desc.trim()
665 gsObserve.set(
"profiles", list);
668 var EventUpdateSettings =
function() {
670 var source = gsObserve.source;
681 if (ValidateSettings() && $.homecuValidator.validate()) {
683 if (source.e_profile) {
684 if (typeof source.e_profile ==
"string") {
689 if (source.e_profile != source.o_profile) {
690 groupData.gProfile = source.e_profile;
693 if (source.e_profile.e_desc != source.o_profile) {
694 groupData.gProfile = source.e_profile.e_desc;
700 if (source.e_group != source.o_group) {
701 groupData.gName = source.e_group;
706 if (gsHasCommercial) {
709 if (source.e_taxid ==
null || source.e_taxid.length == 0) {
710 groupData.gTaxID =
"";
712 var taxID_e =
"" + source.e_taxid;
713 var taxID_o =
"" + source.o_taxid;
715 var taxCD_e = source.e_taxcd;
716 var taxCD_o = source.o_taxcd;
718 groupData.gTaxID = taxCD_e + taxID_e;
723 operation:
"groupUpdateSettings",
725 gSettings: JSON.stringify(groupData)
728 gsDataSource.transport.options.read.type =
"POST";
729 gsDataSource.read(groupRequest);
733 var EventOpenWindow =
function(e) {
734 var windowElement = this.element[0];
735 var windowId = windowElement.id;
741 gsCardWindows.push(
this);
744 var EventCloseWindow =
function(e) {
745 var windowElement = this.element[0];
746 var windowId = windowElement.id;
749 case "discardConfirm":
750 EventPopWindow(windowId);
752 var source = gsObserve.source;
755 source.e_group = source.o_group;
756 source.e_taxid = source.o_taxid;
757 source.e_taxcd = source.o_taxcd;
758 source.e_profile = source.o_profile;
764 if (windowId ==
"gsSettings") {
765 if (ValidateSettings()) {
769 EventPopWindow(windowId);
772 $.homecuValidator.setup({
773 formStatusField:
"formStatus",
774 formValidate:
"cardContainerDiv" 778 EventPopWindow(windowId);
786 var EventPopWindow =
function(windowId) {
788 for (var i = 0; i < gsCardWindows.length; i++) {
789 var openWindow = gsCardWindows[i].element[0];
790 var openId = openWindow.id;
792 if (openId == windowId) {
799 gsCardWindows.splice(popIndex, 1);
803 var InitDataSources =
function() {
804 gsDataSource =
new kendo.data.DataSource({
809 contentType:
"application/x-www-form-urlencoded",
817 requestStart:
function(request) {
820 requestEnd:
function(response) {
821 setTimeout(hideWaitWindow, 500);
823 if (response.hasOwnProperty(
"response")) {
824 if (response.response.hasOwnProperty(
"Results")) {
825 var results = response.response.Results;
827 if (results.hasOwnProperty(
"error")) {
828 $.homecuValidator.homecuResetMessage =
true;
829 $.homecuValidator.displayMessage(results.error, $.homecuValidator.settings.statusError);
830 }
else if (results.hasOwnProperty(
"info")) {
831 $.homecuValidator.homecuResetMessage =
true;
832 $.homecuValidator.displayMessage(results.info, $.homecuValidator.settings.statusSuccess);
835 $.homecuValidator.displayMessage(
"Error Parsing Server", $.homecuValidator.settings.statusError);
838 $.homecuValidator.displayMessage(
"Error Parsing Server", $.homecuValidator.settings.statusError);
842 parse:
function(response) {
845 var resultData =
null;
846 var resultOperation =
null;
848 if (response.hasOwnProperty(
"Results")) {
849 results = response.Results;
850 resultData = results.data;
851 resultOperation = results.operation;
854 if (results.hasOwnProperty(
"errors")) {
858 if (resultData == undefined || resultData ==
null) {
862 setTimeout(
function() {
863 switch (resultOperation) {
864 case "groupReadSettings":
865 DataBuildSettings(resultData.settings);
866 DataBuildProfiles(resultData.profiles);
867 gsSettings.center().open();
869 case "groupUpdateSettings":
870 gsPayload = resultData.encrypt;
871 gsGroup = resultData.group.group;
872 gsCall(
"updateGroupInfo", resultData.group);
873 gsCall(
"updateGroupEncrypt", resultData.encrypt);
875 gsObserve.source.o_group = gsObserve.source.e_group;
879 if (gsHasCommercial) {
880 gsObserve.source.o_taxid = gsObserve.source.e_taxid;
881 gsObserve.source.o_taxcd = gsObserve.source.e_taxcd;
884 if (gsObserve.source.e_profile.e_desc) {
885 gsObserve.source.o_profile = gsObserve.source.e_profile.e_desc;
887 gsObserve.source.o_profile = gsObserve.source.e_profile;
897 var
template= kendo.template($(
"#titleTemplate").html());
898 gsGroup.cardTitle=
"Group Settings";
899 gsSettings.title(
template(gsGroup));
908 var InitDataViews =
function() {
909 gsSettings = $(
"#gsSettings").kendoWindow({
910 title:
"Group Settings",
916 activate: EventOpenWindow,
917 close: EventCloseWindow,
919 this.wrapper.css({ top: 100 });
921 }).data(
"kendoWindow");
923 gsDiscard = $(
"#gsDiscard").kendoDialog({
924 title:
"Discard Changes",
930 show: EventOpenWindow,
931 close: EventCloseWindow,
934 action:
function() { gsAction =
"discardDeny"; }
936 { text:
"Yes", primary:
true,
937 action:
function() { gsAction =
"discardConfirm"; }
940 }).data(
"kendoDialog");
942 gsStatus = $(
"#gsStatus");
945 gsObserve =
new kendo.observable({
952 kendo.bind(
"#gsSettings", gsObserve);
955 var InitDataActions =
function() {
956 $(
"#btnUpdate").on(
"click",
function() {
957 EventUpdateSettings();
959 $(
"#lnkCancel").on(
"click",
function() {
964 this.Open =
function(windowStack) {
966 $.homecuValidator.setup({
967 formStatusField:
"status",
968 formValidate:
"gsSettings" 971 gsCardWindows = windowStack;
973 operation:
"groupReadSettings",
977 gsDataSource.transport.options.read.type =
"POST";
978 gsDataSource.read(groupRequest);
981 this.Close =
function() {
982 gsSettings.destroy();
985 this.Data =
function(payload, group) {
990 this.Init =
function(hubCall, cardContainer) {
992 gsCardContainer = cardContainer;
998 gsCall(
"GroupSettings",
this);