Odyssey
aGroupSettings.prg
1 <?php
2 /**
3  * @package GroupHub
4  * @author MGHandy
5  *
6  * @uses use this scriptto interact with the Group Info feature of the Group Hub.
7  * This script allows for printing of the needed html/javascript content, and
8  * manipulation of the group information data such as group profile, group name
9  * and primary user.
10  *
11  * @param operation string : determines what action to take with the script.
12  * operation = "" will print the needed html/javascript content.
13  * @param payload string : string containing the encrypted group data
14  * needed by each of the different actions.
15  * @param gInfo string : json encoded string of data to be updated. Updates to primary
16  * user, group name and profile happend all at one time.
17  *
18  * @return json encoded data
19  */
20 require_once("$admLibrary/aGroupSupport.i");
21 require_once("$sharedLibrary/sFeatureMnu.i");
22 
23 try {
24  $admVars = array();
25  $admOk = array(
26  "operation" => array("filter" => FILTER_SANITIZE_STRING),
27  "payload" => array("filter" => FILTER_SANITIZE_STRING),
28  "gSettings" => array("filter" => FILTER_SANITIZE_STRING),
29  );
30 
31  HCU_ImportVars($admVars, "GROUP_SETTINGS", $admOk);
32 
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;
36 
37  // decrypt payload only if there is one
38  // payload won't exist if operation is empty
39  // operation empty means just load card content
40  $sGroup = $sPayload ?
41  GroupDecrypt($SYSENV, $Cu, $sPayload) :
42  null;
43 
44  // load context depending on payload existence.
45  $sContext = $sPayload ?
46  GroupContext($SYSENV, $Cu, $sGroup['group']) :
47  GroupContext($SYSENV, $Cu);
48 
49  $aryResult = array();
50  $aryReply = array();
51 
52  switch ($sOperation) {
53  case "":
54  // use the feature menu to determine if the cu has
55  // access to ach commercial features, ACHPMT/ACHCOL
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;
60  }
61  PrintGroupSettings($featureMenuHasACH);
62  break;
63  case "groupReadSettings":
64  header('Content-type: application/json');
65  $gProfiles = GroupReadProfiles($SYSENV, $dbh, $sContext);
66  $gSettings = GroupReadSettings($SYSENV, $dbh, $sContext);
67 
68  $aryResult['data']['settings'] = $gSettings['settings'];
69  $aryResult['data']['profiles'] = $gProfiles['profiles'];
70  GroupReply($aryResult, $aryReply, $sOperation);
71  break;
72  case "groupUpdateSettings":
73  header('Content-type: application/json');
74  $gValidate = GroupValidateSettings($SYSENV, $sSettings);
75 
76 
77  // update group name
78  if (HCU_array_key_exists("info", $gValidate)) {
79  $gInfo = GroupUpdateInfo($SYSENV, $dbh, $sContext, $gValidate['info']);
80  // set new group name
81  $sGroup['group']['g_name'] = $gInfo['info']['group_name'];
82  // set return message
83  $aryResult['info'][] = $gInfo['message'];
84  }
85 
86  // update profile
87  if (HCU_array_key_exists("profile", $gValidate)) {
88  $gProfile = GroupUpdateProfile($SYSENV, $dbh, $sContext, $gValidate['profile']);
89  // set new profile id and name
90  $sGroup['group']['g_profile'] = $gProfile['profile']['name'];
91  $sGroup['group']['p_id'] = $gProfile['profile']['id'];
92  // set return message
93  $aryResult['info'][] = $gProfile['message'];
94  }
95 
96  // re-select group
97  // re-hash group
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);
102 
103  // set result
104  $aryResult['data']['group'] = $sGroup;
105  $aryResult['data']['encrypt'] = $sEncrypt;
106  GroupReply($aryResult, $aryReply, $sOperation);
107  break;
108  default:
109  throw new Exception("Unknown server request: " . $sOperation);
110  break;
111  }
112 
113 } catch (Exception $e) {
114  $aryReply['errors'][] = $e->getMessage();
115  $aryResult['data'] = array();
116  $aryResult['info'] = array();
117 
118  GroupReply($aryResult, $aryReply, $sOperation);
119  exit;
120 }
121 
122 /**
123  * GroupValidateInfo:
124  * @uses validate the incoming data to be updated. this function will take the incoming
125  * group name, group profile, and old/new primary users and set them to valid values
126  * to be inserted or updated int the database.
127  *
128  * @param $pEnv array : environment variable for debugging
129  * @param $pInfo string : json encoded data to be updated
130  *
131  * @return $vInfo array : array of savable data seperated into individual update values.
132  */
133 function GroupValidateSettings($pEnv, $pSettings) {
134  $gSettings = html_entity_decode($pSettings, ENT_QUOTES);
135  $gSettings = json_decode($gSettings, true);
136  $vSettings = array();
137 
138  if (HCU_array_key_exists("gName", $gSettings)) {
139  $vSettings['info']['name'] = prep_save($gSettings['gName'], 50);
140  }
141 
142  if (HCU_array_key_exists("gTaxID", $gSettings)) {
143  $vSettings['info']['taxid'] = prep_save($gSettings['gTaxID'], 10);
144  }
145 
146  if (HCU_array_key_exists("gProfile", $gSettings)) {
147  $vSettings['profile'] = prep_save($gSettings['gProfile'], 255);
148  }
149 
150  return $vSettings;
151 }
152 
153 /**
154  * GroupUpdateProfile:
155  * @uses this function allows for updating a group's profile association. This function
156  * will update the group profile id, delete all group rights from the group, delete any
157  * user rights not in the new profile and return and users that may have different rights
158  * values than the profile allows.
159  *
160  * @param $pEnv array : environment variable for debugging
161  * @param $pDbh object : database access
162  * @param $pContext array : array containing decrypted group data and table identifiers.
163  * @param $pProfile string : name of new profile.
164  *
165  * @return $sqlReturn array : new profile data
166  */
167 function GroupUpdateProfile($pEnv, $pDbh, $pContext, $pProfile) {
168  if ($pProfile == null || $pProfile == "") { return array(); }
169 
170  $gId = $pContext['g_id'];
171  $pId = $pContext['p_id'];
172  $cuTable = $pContext['cu_table'];
173  $cuCode = $pContext['cu_code'];
174 
175  $sqlReturn = array();
176 
177  $pDesc = prep_save($pProfile, 255);
178  $sqlSelect = "SELECT profile_id AS p_id
179  FROM cu_profile
180  WHERE description = '$pDesc'
181  AND cu = '$cuCode'";
182 
183  $sqlSelectRs = db_query($sqlSelect, $pDbh);
184  $sqlSelectRow = db_fetch_assoc($sqlSelectRs);
185  $pId = intval($sqlSelectRow['p_id']);
186 
187  // UPDATE GROUP PROFILE ID
188  $sqlUpdate = "UPDATE {$cuTable}group
189  SET profile_id = $pId
190  WHERE group_id = $gId";
191  $sqlUpdateRs = db_query($sqlUpdate, $pDbh);
192  if (!$sqlUpdateRs) {
193  $pEnv['logger']->error(db_last_error());
194  throw new Exception("Failed to update group profile.");
195  }
196 
197  // DELETE GROUP RIGHTS FOR GROUP ID
198  $sqlDelete = "DELETE FROM {$cuTable}grouprights
199  WHERE group_id = $gId";
200  $sqlDeleteRs = db_query($sqlDelete, $pDbh);
201  if (!$sqlDeleteRs) {
202  $pEnv['logger']->error(db_last_error());
203  throw new Exception("Failed to update group rights.");
204  }
205 
206  // DELETE USER RIGHTS NOT IN NEW PROFILE
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);
215  if (!$sqlDeleteRs) {
216  $pEnv['logger']->error(db_last_error());
217  throw new Exception("Failed to update user rights rights.");
218  }
219 
220  // SELECT USER RIGHTS WITH DIFFERENCES TO NEW PROFILE
221  $sqlColumns = "
222  f.feature_code AS f_code,
223  f.description AS f_desc,
224  u.user_name AS u_user";
225  $sqlDiff = "
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
242  AND ($sqlDiff)";
243  $sqlSelectRs = db_query($sqlSelect, $pDbh);
244  if (!$sqlSelectRs) {
245  $pEnv['logger']->error(db_last_error());
246  throw new Exception("Failed to read user rights.");
247  }
248 
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>&emsp;&emsp;The following users may have feature limits that differ from the new profile.";
253 
254  while ($row = db_fetch_assoc($sqlSelectRs)) {
255  $sqlReturn['message'] .= "<br>&emsp;&emsp;&mdash; User: " . $row['u_user'] . " Feature: " . $row['f_desc'];
256  }
257  }
258 
259  return $sqlReturn;
260 }
261 
262 /**
263  * GroupUpdateInfo:
264  * @uses this function allows for updating a group's name.
265  *
266  * @param $pEnv array : environment variable for debugging
267  * @param $pDbh object : database access
268  * @param $pContext array : array containing decrypted group data and table identifiers.
269  * @param $pInfo array : array of group information values to update.
270  *
271  * @return $sqlReturn array : new group data
272  */
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'];
278 
279  $sqlReturn = array();
280  $sqlColumns = array();
281  $sqlValues = array();
282 
283  // add group name change
284  if (HCU_array_key_exists("name", $pInfo)) {
285  $sqlColumns[] = "group_name";
286  $sqlValues[] = "'{$pInfo['name']}'";
287  }
288 
289  if (HCU_array_key_exists("taxid", $pInfo)) {
290  $sqlColumns[] = "tax_id";
291  $sqlValues[] = "'{$pInfo['taxid']}'";
292  }
293 
294  $sqlColumns = implode(",", $sqlColumns);
295  $sqlValues = implode(",", $sqlValues);
296 
297  $sqlUpdate = "UPDATE {$cuTable}group
298  SET ($sqlColumns) = ($sqlValues)
299  WHERE group_id = $gId
300  AND profile_id= $pId
301  RETURNING group_name, tax_id";
302 
303  $sqlUpdateRs = db_query($sqlUpdate, $pDbh);
304  if (!$sqlUpdateRs) {
305  $pEnv['logger']->error(db_last_error());
306  throw new Exception("Failed to update group information.");
307  }
308 
309  $sqlReturn['info'] = db_fetch_all($sqlUpdateRs)[0];
310  $sqlReturn['message'] = "Group information has been updated successfully.";
311  return $sqlReturn;
312 }
313 
314 /**
315  * GroupReadSettings:
316  * @uses this function allows for reading the basic information of this group.
317  *
318  * @param $pEnv array : environment variable for debugging
319  * @param $pDbh object : database access
320  * @param $pContext array : array containing decrypted group data and table identifiers.
321  *
322  * @return $sqlReturn array : group information
323  */
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'];
329 
330  $sqlReturn = array();
331 
332  $sqlColumns = "
333  g.group_name AS g_name,
334  g.tax_id AS g_taxid,
335  p.description AS p_desc";
336 
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";
342 
343  $sqlSelectRs = db_query($sqlSelect, $pDbh);
344  if (!$sqlSelectRs) {
345  $pEnv['logger']->error(db_last_error());
346  throw new Exception("Failed to read group information.");
347  }
348 
349  $sqlReturn['settings'] = db_fetch_all($sqlSelectRs)[0];
350  return $sqlReturn;
351 }
352 
353 /**
354  * GroupReadProfiles:
355  * @uses this function allows for reading the list of available profiles.
356  *
357  * @param $pEnv array : environment variable for debugging
358  * @param $pDbh object : database access
359  * @param $pContext array : array containing decrypted group data and table identifiers.
360  *
361  * @return $sqlReturn array : list of profiles
362  */
363 function GroupReadProfiles($pEnv, $pDbh, $pContext) {
364  $cuCode = $pContext['cu_code'];
365 
366  $sqlReturn = array();
367  $sqlColumn = "
368  description AS p_desc";
369 
370  $sqlSelect = "SELECT $sqlColumn
371  FROM cu_profile
372  WHERE cu = '$cuCode'
373  ORDER BY description ASC";
374 
375  $sqlSelectRs = db_query($sqlSelect, $pDbh);
376  if (!$sqlSelectRs) {
377  $pEnv['logger']->error(db_last_error());
378  throw new Exception("Failed to read profiles.");
379  }
380 
381  $sqlReturn['profiles'] = db_fetch_all($sqlSelectRs);
382  return $sqlReturn;
383 }
384 ?>
385 
386 <?php
387 /**
388  * PrintGroupUsers:
389  * @uses this function allows for printing the html/javascript content needed to interact
390  * with the group users feature.
391  */
392 function PrintGroupSettings($featureMenuHasACH) { ?>
393 <div id="gsSettings">
394  <div id="status"></div>
395  <div class="col-sm-12">&nbsp;</div>
396  <div class="well well-sm col-sm-12">
397  <div class="row">
398  <div class="col-sm-5">
399  <label for="gsInpProfile">
400  <span>Profile</span>
401  <span class="fa fa-asterisk" style="color: #f0ad4e;"
402  data-bind="visible: source.e_dirty"></span>
403  </label>
404  </div>
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"
410  data-bind="
411  source: profiles,
412  value: source.e_profile,
413  events: { change: change }">
414  </div>
415  </div>
416  &nbsp;
417  <div class="row">
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>
423  </label>
424  </div>
425  <div class="col-sm-7"><input class="hcu-all-100 k-input k-textbox" id="gsInpGroup" name="gsInpGroup"
426  maxlength="50"
427  data-bind="
428  value: source.e_group,
429  events: { change: change }"
430  data-required-msg="Group name is required"
431  required></div>
432  </div>
433  <?php if ($featureMenuHasACH) : ?>
434  &nbsp;
435  <div class="row">
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>
441  </label>
442  </div>
443  <div class="col-sm-7">
444  <input class="hcu-all-100" id="gsInpTaxID" name="gsInpTaxID"
445  maxlength="9"
446  homecu-minlen="9"
447  data-homecuCustomMinLen-msg="Commercial Tax ID requires 9 characters"
448  data-role="numerictextbox"
449  data-spinners="false"
450  data-decimals="0"
451  data-format="#"
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}">
456  <span> EIN</span>
457  </label>
458  &nbsp;
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}">
462  <span> SSN</span>
463  </label>
464  </div>
465  </div>
466  <?php endif; ?>
467  </div>
468 
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>
473  &ensp;
474  <a href="##" id="btnUpdate" class="k-button k-primary">
475  <i class="fa fa-check fa-lg"></i>
476  Update
477  </a>
478  </div>
479  </div>
480 </div>
481 
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>
486  </div>
487 </div>
488 <?php
489 /**
490  * @package GroupSettings:
491  * @uses This object is used to display and interact with the group settings feature.
492  *
493  * @var Init public: public call to initialize data/view/action objects
494  * @var Data public: public call to set/reset encrypted data
495  * @var Open public: public call to open the group rights module/window
496  * @var Close public: public call to close the group rights module/window
497  *
498  * @var InitDataSources private: initialize all needed data sources/objects
499  * @var InitDataViews private: initialize all data views/html elements
500  * @var InitDataActions private: initialize all user actions on html.
501  *
502  * @var EventOpenDialog private: open kendoDialog/kendoWindow objects
503  * @var EventClosedialog private: close kendoDialog/kendoWindow objects
504  * @var EventPopDialog private: remove the correct window from the window stack.
505  *
506  * @var EventOpenInfo private: send request to read/open group info
507  * @var EventCancelInfo private: close group rights window, canceling changes
508  * @var EventUpdateInfo private: send crud request for group info, profile and primary
509  * user updates.
510  * @var Event* private: the other event functions not listed above are custom
511  * calls for kendo bjects and other helper functions that are explained by the
512  * function name.
513  *
514  * @var Validate* private: these functions facilitate validation of particular
515  * pieces of the interface. Uses explained by function name.
516  *
517  * @var DataBuild* private: these functions facilitate re-constructing data for
518  * proper use in the other js functions and html displays.
519  *
520  * @var Action* private: these functions are calls from kendoDialog actions
521  * uses explained by function name.
522  *
523  * @var ClearGroupInfo private: clear information displayed in the information bar.
524  * @var ShowGroupInfo private: show any information return by the server.
525  */
526 ?>
527 <script type="text/javascript">
528 
529 var GroupSettings = function() {
530  var gsCardContainer = null;
531  var gsCardWindows = null;
532 
533  var gsPayload = null;
534  var gsGroup = null;
535  var gsCall = null;
536  var gsAction = null;
537  var gsDataSource = null;
538 
539  var gsSettings = null;
540  var gsObserve = null;
541 
542  var gsHasCommercial = <?php echo HCU_JsonEncode($featureMenuHasACH); ?>;
543 
544  var ValidateSettings = function() {
545  var source = gsObserve.source;
546 
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;
552 
553  if (source.e_profile) {
554  if (typeof source.e_profile == "string") {
555  profile_e = source.e_profile;
556  } else {
557  profile_e = source.e_profile.e_desc;
558  }
559  }
560 
561  if (profile_e != profile_o) {
562  profileWrn.show();
563  } else {
564  profileWrn.hide();
565  }
566 
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();
572 
573  if (group_e != group_o) {
574  groupWrn.show();
575  } else {
576  groupWrn.hide();
577  }
578 
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]);
586 
587  // because masked textboxes don't strip the prompt chars, i.e. underscore
588  // we must strip them here to test the actual values.
589  var taxID_e = source.e_taxid == null ? "" : "" + source.e_taxid;
590  var taxID_o = source.o_taxid == null ? "" : "" + source.o_taxid;
591 
592  var taxCD_e = source.e_taxcd;
593  var taxCD_o = source.o_taxcd;
594 
595  taxIDChanged =
596  (taxID_e != taxID_o) ||
597  (taxCD_e != taxCD_o);
598 
599  if (taxIDChanged) {
600  taxWrn.show();
601  } else {
602  taxWrn.hide();
603  }
604 
605  // since the validator only looks for required
606  // fields we must set the border highlight here.
607  if (taxID_e == null || taxID_e.length == 0 || taxID_e.length == 9) {
608  $("#gsInpTaxID").parent().css("border-color", "#ceced2");
609  } else {
610  $("#gsInpTaxID").parent().css("border-color", "#d80000");
611  }
612  }
613 
614  source.e_dirty =
615  profile_e != profile_o ||
616  group_e != group_o ||
617  taxIDChanged;
618 
619  return source.e_dirty;
620  }
621 
622  var DataBuildSettings = function(data) {
623  var info = {
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(),
628  e_dirty: false
629  };
630 
631  // only setup tax id fields if the credit union
632  // has access to ach commercial features.
633  if (gsHasCommercial) {
634  var taxID = data.g_taxid == null ? "" : data.g_taxid;
635  var taxIDType = 1;
636  // if taxid is not empty, strip first digit
637  // this digit is a code identifier for EIN or
638  // User Defined Number.
639 
640  // This first digit will be the checkbox value under the
641  // tax id field.
642  taxIDType = taxID.length > 0 ? taxID.substring(0, 1) : "1";
643  taxID = taxID.length > 0 ? taxID.substring(1) : taxID;
644 
645  info.o_taxid = taxID;
646  info.e_taxid = taxID;
647  info.o_taxcd = taxIDType;
648  info.e_taxcd = taxIDType;
649  }
650 
651  gsObserve.set("source", info);
652  }
653 
654  var DataBuildProfiles = function(data) {
655  var list = [];
656  for (var i = 0; i < data.length; i++) {
657  var profile = {
658  o_desc: data[i].p_desc.trim(),
659  e_desc: data[i].p_desc.trim()
660  };
661 
662  list.push(profile);
663  }
664 
665  gsObserve.set("profiles", list);
666  }
667 
668  var EventUpdateSettings = function() {
669  var groupData = {};
670  var source = gsObserve.source;
671 
672  // the validator refuses to correctly validate any fields when the
673  // tax id fields are present on screen, we will not use the validator.
674 
675  // unresolved: when tax id fields are on screen, group name doesn't
676  // show validation message when using the homecuvalidator.
677  // unresolved: when tax id fields are on screen, commercial tax id
678  // doesn't outline in red when using the homecuvalidator.
679  var errors = [];
680 
681  if (ValidateSettings() && $.homecuValidator.validate()) {
682  // change to profile
683  if (source.e_profile) {
684  if (typeof source.e_profile == "string") {
685 
686  // check if changed
687  // because changing the dropdown list creates an init object
688  // we can get the value two ways
689  if (source.e_profile != source.o_profile) {
690  groupData.gProfile = source.e_profile;
691  }
692  } else {
693  if (source.e_profile.e_desc != source.o_profile) {
694  groupData.gProfile = source.e_profile.e_desc;
695  }
696  }
697  }
698 
699  // change to group name
700  if (source.e_group != source.o_group) {
701  groupData.gName = source.e_group;
702  }
703 
704  // only update tax id fields if the credit union has access to
705  // ach commercial features.
706  if (gsHasCommercial) {
707  // check if null, empty field will come out null
708  // sen empty string
709  if (source.e_taxid == null || source.e_taxid.length == 0) {
710  groupData.gTaxID = "";
711  } else {
712  var taxID_e = "" + source.e_taxid;
713  var taxID_o = "" + source.o_taxid;
714 
715  var taxCD_e = source.e_taxcd;
716  var taxCD_o = source.o_taxcd;
717 
718  groupData.gTaxID = taxCD_e + taxID_e;
719  }
720  }
721 
722  var groupRequest = {
723  operation: "groupUpdateSettings",
724  payload: gsPayload,
725  gSettings: JSON.stringify(groupData)
726  };
727 
728  gsDataSource.transport.options.read.type = "POST";
729  gsDataSource.read(groupRequest);
730  }
731  }
732 
733  var EventOpenWindow = function(e) {
734  var windowElement = this.element[0];
735  var windowId = windowElement.id;
736 
737  switch (windowId) {
738 
739  }
740 
741  gsCardWindows.push(this);
742  }
743 
744  var EventCloseWindow = function(e) {
745  var windowElement = this.element[0];
746  var windowId = windowElement.id;
747 
748  switch (gsAction) {
749  case "discardConfirm":
750  EventPopWindow(windowId);
751 
752  var source = gsObserve.source;
753 
754  // reset info
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;
759 
760  gsAction = null;
761  gsSettings.close();
762  break;
763  default:
764  if (windowId == "gsSettings") {
765  if (ValidateSettings()) {
766  e.preventDefault();
767  gsDiscard.open();
768  } else {
769  EventPopWindow(windowId);
770 
771  // reset validator to hub script
772  $.homecuValidator.setup({
773  formStatusField: "formStatus",
774  formValidate: "cardContainerDiv"
775  });
776  }
777  } else {
778  EventPopWindow(windowId);
779  }
780  break;
781  }
782 
783  gsAction = null;
784  }
785 
786  var EventPopWindow = function(windowId) {
787  var popIndex = -1;
788  for (var i = 0; i < gsCardWindows.length; i++) {
789  var openWindow = gsCardWindows[i].element[0];
790  var openId = openWindow.id;
791 
792  if (openId == windowId) {
793  popIndex = i;
794  break;
795  }
796  }
797 
798  if (popIndex > -1) {
799  gsCardWindows.splice(popIndex, 1);
800  }
801  }
802 
803  var InitDataSources = function() {
804  gsDataSource = new kendo.data.DataSource({
805  transport: {
806  read: {
807  url: "main.prg",
808  dataType: "json",
809  contentType: "application/x-www-form-urlencoded",
810  type: "GET",
811  data: {
812  ft: "102104"
813  },
814  cache: false
815  }
816  },
817  requestStart: function(request) {
818  showWaitWindow();
819  },
820  requestEnd: function(response) {
821  setTimeout(hideWaitWindow, 500);
822 
823  if (response.hasOwnProperty("response")) {
824  if (response.response.hasOwnProperty("Results")) {
825  var results = response.response.Results;
826 
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);
833  }
834  } else {
835  $.homecuValidator.displayMessage("Error Parsing Server", $.homecuValidator.settings.statusError);
836  }
837  } else {
838  $.homecuValidator.displayMessage("Error Parsing Server", $.homecuValidator.settings.statusError);
839  }
840  },
841  schema: {
842  parse: function(response) {
843 
844  var results = null;
845  var resultData = null;
846  var resultOperation = null;
847 
848  if (response.hasOwnProperty("Results")) {
849  results = response.Results;
850  resultData = results.data;
851  resultOperation = results.operation;
852  }
853 
854  if (results.hasOwnProperty("errors")) {
855  return [];
856  }
857 
858  if (resultData == undefined || resultData == null) {
859  return [];
860  }
861 
862  setTimeout(function() {
863  switch (resultOperation) {
864  case "groupReadSettings":
865  DataBuildSettings(resultData.settings);
866  DataBuildProfiles(resultData.profiles);
867  gsSettings.center().open();
868  break;
869  case "groupUpdateSettings":
870  gsPayload = resultData.encrypt;
871  gsGroup = resultData.group.group;
872  gsCall("updateGroupInfo", resultData.group);
873  gsCall("updateGroupEncrypt", resultData.encrypt);
874 
875  gsObserve.source.o_group = gsObserve.source.e_group;
876 
877  // only update taxid values if the credit union
878  // has access to ach commercial features.
879  if (gsHasCommercial) {
880  gsObserve.source.o_taxid = gsObserve.source.e_taxid;
881  gsObserve.source.o_taxcd = gsObserve.source.e_taxcd;
882  }
883 
884  if (gsObserve.source.e_profile.e_desc) {
885  gsObserve.source.o_profile = gsObserve.source.e_profile.e_desc;
886  } else {
887  gsObserve.source.o_profile = gsObserve.source.e_profile;
888  }
889 
890  ValidateSettings();
891  break;
892  }
893 
894  // this code was moved from the read settings case above because
895  // the update case was not updating the group name for the window
896  // title.
897  var template= kendo.template($("#titleTemplate").html());
898  gsGroup.cardTitle= "Group Settings";
899  gsSettings.title(template(gsGroup));
900  }, 500);
901 
902  return [];
903  }
904  }
905  });
906  }
907 
908  var InitDataViews = function() {
909  gsSettings = $("#gsSettings").kendoWindow({
910  title: "Group Settings",
911  minWidth: "75%",
912  maxWidth: "90%",
913  modal: true,
914  visible: false,
915  resizable: false,
916  activate: EventOpenWindow,
917  close: EventCloseWindow,
918  open: function() {
919  this.wrapper.css({ top: 100 });
920  }
921  }).data("kendoWindow");
922 
923  gsDiscard = $("#gsDiscard").kendoDialog({
924  title: "Discard Changes",
925  modal: true,
926  minWidth: 300,
927  maxWidth: 500,
928  visible: false,
929  resizable: false,
930  show: EventOpenWindow,
931  close: EventCloseWindow,
932  actions: [
933  { text: "No",
934  action: function() { gsAction = "discardDeny"; }
935  },
936  { text: "Yes", primary: true,
937  action: function() { gsAction = "discardConfirm"; }
938  }
939  ]
940  }).data("kendoDialog");
941 
942  gsStatus = $("#gsStatus");
943  gsStatus.hide();
944 
945  gsObserve = new kendo.observable({
946  source: null,
947  profiles: [],
948  change: function() {
949  ValidateSettings();
950  }
951  });
952  kendo.bind("#gsSettings", gsObserve);
953  }
954 
955  var InitDataActions = function() {
956  $("#btnUpdate").on("click", function() {
957  EventUpdateSettings();
958  });
959  $("#lnkCancel").on("click", function() {
960  gsSettings.close();
961  });
962  }
963 
964  this.Open = function(windowStack) {
965  // setup validator
966  $.homecuValidator.setup({
967  formStatusField: "status",
968  formValidate: "gsSettings"
969  });
970 
971  gsCardWindows = windowStack;
972  var groupRequest = {
973  operation: "groupReadSettings",
974  payload: gsPayload
975  };
976 
977  gsDataSource.transport.options.read.type = "POST";
978  gsDataSource.read(groupRequest);
979  }
980 
981  this.Close = function() {
982  gsSettings.destroy();
983  }
984 
985  this.Data = function(payload, group) {
986  gsPayload = payload;
987  gsGroup = group;
988  }
989 
990  this.Init = function(hubCall, cardContainer) {
991  gsCall = hubCall;
992  gsCardContainer = cardContainer;
993 
994  InitDataSources();
995  InitDataViews();
996  InitDataActions();
997 
998  gsCall("GroupSettings", this);
999  }
1000 }
1001 </script>
1002 <?php }