Odyssey
aAccessControl.data
1 <?php
2 
3 /**
4  * function DeleteSubAccounts($pEnv, $accountnumber, $subaccounts)
5  * This deletes one or more subaccounts.
6  *
7  * @param $pEnv -- the environment
8  * @param $accountnumber -- the account number to delete sub accounts for
9  * @param $subaccounts -- the subaccounts to delete
10  *
11  * @return $error -- array of errors (0 or more)
12  * @return $code -- 0 if successful, nonzero otherwise
13  * @return $showAddNewAccount -- if new account option should be shown
14  */
15 function DeleteSubAccounts($pEnv, $accountnumber, $subaccounts) {
16  $showAddNewAccount = false;
17 
18  try {
19  $dbh = $pEnv["dbh"];
20  $userId = $pEnv["userId"];
21  $Cu = $pEnv["Cu"];
22  $Cn = $pEnv["Cn"];
23  $allowZeroes = $pEnv["allowZeroes"];
24  $disallowMultipleAccounts = $pEnv["disallowMultipleAccounts"];
25 
26  // If don't allow leading zeroes, strip out the leading zeroes.
27  if (!$allowZeroes) {
28  $accountnumber = preg_replace('/^0+/', '', trim($accountnumber));
29  }
30 
31  if ($subaccounts == "") {
32  throw new exception("Subaccounts are required.", 1);
33  }
34  $subaccounts = hcu_JsonDecode($subaccounts);
35  if (!is_array($subaccounts)) {
36  throw new exception("Subaccounts are required.", 2);
37  }
38  $forDeletion = array();
39  foreach($subaccounts as $subaccount) {
40  if (!HCU_array_key_exists("accounttype", $subaccount) || !HCU_array_key_exists("certnumber", $subaccount)
41  || !HCU_array_key_exists("recordtype", $subaccount)) {
42  throw new exception("Subaccounts are malformed.", 3);
43  }
44  $subaccount["_action"] = "delete";
45  $subaccount["user_id"] = $userId;
46  $subaccount["accountnumber"] = $accountnumber;
47  $accountDelete[] = $subaccount;
48  }
49 
50  $datatable = "useraccounts";
51  $forDeletion = array($datatable => $accountDelete);
52 
53  $sql = "select email from cuadminusers
54  where user_name = '" . prep_save($Cn, 50) . "'
55  and cu = '" . prep_save($Cu, 10) . "'";
56  $sth = db_query($sql, $dbh);
57  if (!$sth) {
58  throw new exception("email query failed.", 4);
59  }
60  $email = db_fetch_row($sth)[0];
61 
62  $context = "admin";
63  $script = "userSupportAccessControl.prg";
64  $addr = trim($_SERVER["REMOTE_ADDR"]);
65  $vars = array("cu" => $Cu);
66 
67  if (!db_work ($dbh, HOMECU_WORK_BEGIN)) {
68  throw new exception("begin query failed.", 6);
69  }
70 
71  // deleting from useraccounts table
72  $results = DataUserTableUpdate($dbh, $vars, null, $forDeletion, $userId, "ACCESS_DEL", $context,
73  $script, "A", "Primary User Access Delete", $Cn, $email, $addr);
74  if ($results === false) {
75  throw new exception("Deleting from useraccounts table failed.", 105);
76  }
77 
78 
79  // deleting from cu_alerts table
80  $forDeletion = array();
81  // $alertDelete = array();
82  $alerts = array();
83  $datatable = "cu_alerts";
84  //remove unneeded array value for cu_alert deletion
85  foreach($accountDelete as $subKey => $subArray) {
86  if (HCU_array_key_exists('recordtype', $subArray)) {
87  unset($accountDelete[$subKey]['recordtype']);
88  }
89  $accountType = HCU_array_key_value('accounttype', $accountDelete[$subKey]);
90  $certNumber = HCU_array_key_value('certnumber', $accountDelete[$subKey]);
91  // look up ids of any alert records
92  $alertSql = "select id
93  from cu_alerts where user_id = '" . prep_save(intval($userId)) . "'
94  AND accountnumber = '" . prep_save($accountnumber, 12) . "'
95  AND accounttype = '" . prep_save($accountType, 25) . "'
96  AND certnumber = " . prep_save(intval($certNumber)) . " ";
97  $sth = db_query($alertSql, $dbh);
98 
99  if (!$sth) {
100  throw new exception("cu_alerts query failed.", 107);
101  }
102  if (db_num_rows($sth) > 0) {
103  while ($result = db_fetch_row($sth)) {
104  $alerts['id'] = $result[0];
105  $alerts["_action"] = "delete";
106  $alertDelete[] = $alerts;
107  }
108  }
109  }
110 
111  if (isset($alertDelete)) {
112  $forDeletion = array($datatable => $alertDelete);
113  $results = DataUserTableUpdate($dbh, $vars, null, $forDeletion, $userId, "ACCESS_DEL", $context,
114  $script, "A", "Primary User Access Delete", $Cn, $email, $addr);
115  if ($results === false) {
116  throw new exception("Deleting from alerts table failed.", 105);
117  }
118  }
119 
120  // deleting from cu_scheduledtxn table
121  $forDeletion = array();
122  $sched = array();
123  $datatable = "cu_scheduledtxn";
124 
125  //remove unneeded array value for cu_scheduledtxn deletion
126  foreach($accountDelete as $subKey => $subArray) {
127  $accountType = HCU_array_key_value('accounttype', $accountDelete[$subKey]);
128  // look up ids of any alert records
129  $schedSql = "select id, txn_data from cu_scheduledtxn
130  where user_id = '" . prep_save(intval($userId)) . "'
131  AND CU = '" . prep_save($Cu, 10) . "' ";
132  $sth = db_query($schedSql, $dbh);
133 
134  if (!$sth) {
135  throw new exception("cu_scheduledtxn query failed.", 107);
136  }
137  $row = 0;
138  if (db_num_rows($sth) > 0) {
139  while ($result = db_fetch_assoc($sth, $row++)) {
140  $txnData = HCU_JsonDecode( $result["txn_data"], false );
141  if ($txnData['txn']['frommember'] == $accountnumber && $txnData['txn']['fromsuffix'] == $accountType ) {
142  $sched['id'] = $result['id'];
143  $sched["_action"] = "delete";
144  $schedDelete[] = $sched;
145  }
146  }
147  }
148  }
149 
150  if (isset($schedDelete)) {
151  $forDeletion = array($datatable => $schedDelete);
152  $results = DataUserTableUpdate($dbh, $vars, null, $forDeletion, $userId, "ACCESS_DEL", $context, $script,
153  "A", "Primary User Access Delete", $Cn, $email, $addr);
154  if ($results === false) {
155  throw new exception("Deleting from scheduledtxn table failed.", 105);
156  }
157  }
158 
159  $sql = "select 'FOUND' from ${Cu}useraccounts
160  where user_id = " . prep_save(intval($userId)) . "
161  and accountnumber = '" . prep_save($accountnumber, 12) . "'";
162  $sth = db_query($sql, $dbh);
163 
164  if (!$sth) {
165  throw new exception("found query failed.", 107);
166  }
167 
168  if (db_num_rows($sth) == 0) {
169 
170  if ($disallowMultipleAccounts) {
171  // This means that there are no accounts anymore. So show add button.
172  $sql = "select 'FOUND' from ${Cu}useraccounts where user_id = " . prep_save(intval($userId));
173  $sth = db_query($sql, $dbh);
174 
175  if (!$sth) {
176  throw new exception("found query failed.", 110);
177  }
178 
179  $showAddNewAccount = db_num_rows($sth) == 0;
180  }
181  $sql = "delete from ${Cu}memberacctrights
182  where user_id = " . prep_save(intval($userId)) . "
183  and accountnumber = '" . prep_save($accountnumber, 12) . "'";
184  $sth = db_query($sql, $dbh);
185  if (!$sth) {
186  throw new exception("acct rights delete failed.", 108);
187  }
188  }
189 
190  if (!db_work($dbh, HOMECU_WORK_COMMIT)) {
191  throw new exception("commit work failed.", 109);
192  }
193 
194  } catch(exception $e) {
195  if ($e->getCode() >= 100) {
196  db_work($dbh, HOMECU_WORK_ROLLBACK); // Got greater problems if this fails.
197  }
198 
199  return array("error" => array($e->getMessage()), "code" => $e->getCode());
200  }
201  return array("error" => array(), "code" => 0, "showAddNewAccount" => $showAddNewAccount);
202 }
203 
204 /**
205  * function GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber)
206  * This function will get subaccount data for an account by querying what is already in the table for the primary user.
207  *
208  * @param $dbh -- the database connection
209  * @param $Cu -- the credit union
210  * @param $userId -- the user id
211  * @param $accountnumber -- the account number
212  *
213  * @return $code -- either 666 or 101
214  * @return $errors -- array of zero or more errors
215  * @return $data -- like is in the spoof accounts function and the real one.)
216  */
217 function GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber) {
218  try {
219  $subquery = "select x.certnumber || trim(recordtype) || trim(x.accountnumber) || trim(x.accounttype) as key, trim(x.accountnumber),
220  trim(x.accounttype), x.certnumber, x.display_name, x.recordtype as type
221  from ${Cu}useraccounts x
222  inner join (
223  select b.user_id from ${Cu}user a
224  inner join ${Cu}user b on a.user_id = $userId and a.group_id = b.group_id and b.is_group_primary limit 1) y
225  on x.user_id = y.user_id where trim(x.accountnumber) = '" . prep_save($accountnumber, 12) . "'";
226 
227  $sql = "select ua.accountnumber, ua.accounttype, ua.certnumber, ab.deposittype, ua.type, coalesce(ab.description, ua.display_name) as description,
228  ab.may_deposit, ab.may_withdraw
229  from (
230  select certnumber || 'D' || trim(accountnumber) || trim(accounttype) as key,
231  trim(description), may_deposit, may_withdraw, '' as deposittype, 'D' as type, trim(accounttype)
232  from ${Cu}accountbalance where accountnumber = '" . prep_save($accountnumber, 12) . "'
233  union all
234  select '0' || 'T' || trim(accountnumber) || trim(accounttype) || '#' || trim(tomember) as key,
235  trim(description), true, false, deposittype, 'T', trim(accounttype)
236  from ${Cu}crossaccounts where accountnumber = '" . prep_save($accountnumber, 12) . "' and deposittype <> 'L'
237  union all
238  select '0' || 'L' || trim(accountnumber) || trim(loannumber) as key,
239  trim(description), may_payment, may_addon, '', 'L', trim(loannumber)
240  from ${Cu}loanbalance where accountnumber = '" . prep_save($accountnumber, 12) . "'
241  union all
242  select '0' || 'P' || trim(accountnumber) || trim(accounttype) || '#' || trim(tomember) as key,
243  trim(description), false, false, deposittype, 'P', trim(accounttype)
244  from ${Cu}crossaccounts where accountnumber = '" . prep_save($accountnumber, 12) . "' and deposittype = 'L'
245  ) as ab(key, description, may_deposit, may_withdraw, deposittype, type, accounttype)
246  right join ($subquery and recordtype in ('D', 'T', 'L', 'P')) as ua(key, accountnumber, accounttype, certnumber, display_name)
247  on ab.key = ua.key order by ab.accounttype";
248  $sth = db_query($sql, $dbh);
249 
250  if (!$sth) {
251  throw new exception("Deposit query failed.", 1);
252  }
253 
254  $depositList = array();
255  $loanList = array();
256  $xacList = array();
257  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
258  // Need to use true or false for may_payment and may_addon because that is what the actual live function is doing.
259  $row["may_deposit"] = HCU_array_key_exists("may_deposit", $row) && isset($row["may_deposit"]) ? trim($row["may_deposit"]) == "t" : true;
260  $row["may_withdraw"] = HCU_array_key_exists("may_withdraw", $row) && isset($row["may_withdraw"]) ? trim($row["may_withdraw"]) == "t" : true;
261 
262  switch($row["type"]) {
263  case "D":
264  $depositList[] = $row;
265  break;
266  case "L":
267  $row ["loannumber"] = $row ["accounttype"];
268  $loanList[] = $row;
269  break;
270  case "T":
271  case "P":
272  $explode = explode("#", $row["accounttype"]);
273  $row["accounttype"] = $explode[0];
274  $row["tomember"] = $explode[1];
275  $xacList[] = $row;
276  break;
277  }
278  }
279  } catch(exception $e) {
280  return array("code" => "666");
281  }
282  return array("code" => "000", "data" => array("accounts" => array("deposit" => $depositList, "loan" => $loanList, "xa" => $xacList)));
283 }
284 
285 /**
286  * function GetAccountFromCore($SYSENV, $accountnumber, $isPrimary)
287  * This will get data from the data (if the user is primary; otherwise, it will get the data from the primary user of the group.)
288  *
289  * @param $SYSENV -- the environment
290  * @param $accountnumber -- the account number
291  * @param $isPrimary -- if the user is the primary user for the group
292  *
293  * @return $error -- array of errors (0 or more)
294  * @return $code -- 0 if successful, nonzero otherwise
295  * @return $accountInfo -- the account information
296  * @return $subaccountInfo -- the subaccount information
297  */
298 function GetAccountFromCore($SYSENV, $accountnumber, $isPrimary) {
299  // TODO: remove this and spoof logic when have batch working correctly
300  $live = $SYSENV["live"];
301  $logger = $SYSENV["logger"];
302  $dbh = $SYSENV["dbh"];
303  $Cu = $SYSENV["Cu"];
304  $allowZeroes = $SYSENV["allowZeroes"];
305  $userId = $SYSENV["userId"];
306 
307  try {
308 
309  // If don't allow leading zeroes, strip out the leading zeroes.
310  if (!$allowZeroes) {
311  $accountnumber = preg_replace('/^0+/', '', trim($accountnumber));
312  }
313 
314  // Go get the data.
315 
316  if ( $live == "Y" ) {
317  $SYSENV['SYSENV']['logger'] = $logger; // ** Required for the lower level functions as they expect the information to be in the "SYSENV" structure
318  $SYSENV['SYSENV']['devmode'] = $SYSENV['devmode'];
319  $fullData = $isPrimary ? FindMemberAccounts($SYSENV, array("member" => $accountnumber, "email" => "")) :
320  GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber);
321  // if no data with MIR packet, try finding without MIR
322  if ($fullData["code"] == "001" || $fullData["code"] == "999") {
323  $fullData = $isPrimary ? FindMemberAccountsWoMIR($dbh, $Cu, $accountnumber) : GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber);
324  }
325  } else {
326  $fullData = $isPrimary ? SpoofFindMemberAccounts($dbh, $Cu, $accountnumber) : GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber);
327  if ($fullData["code"] == "001" || $fullData["code"] == "999") {
328  $fullData = $isPrimary ? FindMemberAccountsWoMIR($dbh, $Cu, $accountnumber) : GetPrimaryMemberAccounts($dbh, $Cu, $userId, $accountnumber);
329  }
330  }
331 
332  switch ($fullData["code"]) {
333  case "001":
334  throw new exception("No data was found.", 1);
335  break;
336  case "999":
337  throw new exception($fullData["error"], 2);
338  break;
339  case "101": // TODO: remove this when batch is working; this comes from Spoof function.
340  case "102": // The correct case with data, but no MIR
341  break;
342  case "000":
343  break; // The correct case with data.
344  default:
345  throw new exception("There was an internal problem.", 3);
346  break;
347  }
348 
349 
350  // I don't care about this data if it isn't a primary user.
351  // Data is not shown anywhere otherwise.
352  // Only shown if primary user and mir data is present
353  if ($isPrimary) {
354  if ( isset($fullData["data"]["mir"]) ) {
355  $accountInfo = $fullData["data"]["mir"];
356 
357  $homePhone = !HCU_array_key_exists("homephone", $accountInfo) ? "" : trim($accountInfo["homephone"]);
358  $cellPhone = !HCU_array_key_exists("cellphone", $accountInfo) ? "" : trim($accountInfo["cellphone"]);
359  $first = !HCU_array_key_exists("firstname", $accountInfo) ? "" : trim($accountInfo["firstname"]);
360  $sec = !HCU_array_key_exists("middlename", $accountInfo) ? "" : trim($accountInfo["middlename"]);
361  $third = !HCU_array_key_exists("lastname", $accountInfo) ? "" : trim($accountInfo["lastname"]);
362  $dob = !HCU_array_key_exists("dob", $accountInfo) ? "" : trim($accountInfo["dob"]);
363  // At this point, DOB should be mm/dd/yyyy. Add a simple test to make sure that that is true.
364 
365  if ($dob != "" && !DateTime::createFromFormat("m/d/Y", $dob)) {
366  // I suppose that the core could not have the DOB information and that would be fine.
367  throw new exception("DOB is invalid.", 5);
368  }
369 
370  $theAccountInfo = array(array("accountnumber" => $accountnumber, "name" => trim("$first $sec $third"), "birthday" => $dob,
371  "primaryPhone" => $homePhone != "" ? $homePhone : $cellPhone));
372  } else {
373  $theAccountInfo = array(array("accountnumber" => $accountnumber, "name" => "", "birthday" => "",
374  "primaryPhone" => ""));
375  }
376 
377  } else {
378  $theAccountInfo = "";
379  }
380 
381  // Will need to put subaccountInfo in one dataSource. Add a flag for deposit or the other thing. Also, get them to have the same columns.
382  $theSubaccountInfo = array();
383  $kendoId = 1;
384 
385  // Add check to exclude subaccounts ALREADY added to the user. Will remove this later using the kendoId.
386  $alreadyExistsCheck = array();
387 
388  $subaccountInfo = $fullData["data"]["accounts"];
389  if (HCU_array_key_exists("deposit", $subaccountInfo)) {
390  foreach($subaccountInfo["deposit"] as $thisRow) {
391  $thisRow["kendoId"] = $kendoId;
392  $thisRow["recordtype"] = "D";
393  $thisRow["isDeposit"] = true;
394 
395  $canDeposit = !HCU_array_key_exists("may_deposit", $thisRow) ? false : $thisRow["may_deposit"];
396  $canWithdraw = !HCU_array_key_exists("may_withdraw", $thisRow) ? false : $thisRow["may_withdraw"];
397  $thisRow["canIntDeposit"] = $canDeposit;
398  $thisRow["canExtDeposit"] = $canDeposit;
399  $thisRow["canIntWithdraw"] = $canWithdraw;
400  $thisRow["canExtWithdraw"] = $canWithdraw;
401 
402  // Also add sort here.
403  $strposAt = strpos($thisRow["accounttype"], "@");
404  $permType = 0;
405  $permAccount = "000";
406  if ($strposAt !== false) {
407  $permType = 1;
408  $permAccount = substr($thisRow["accounttype"], $strposAt + 1);
409  }
410  $thisRow["perm_account_sort"] = $permAccount;
411  $thisRow["perm_type_sort"] = $permType;
412 
413  unset($thisRow["may_deposit"]);
414  unset($thisRow["may_withdraw"]);
415  unset($thisRow["may_payment"]);
416  unset($thisRow["deposittype"]); // Find no use for this here.
417  $theSubaccountInfo[] = $thisRow;
418 
419  $alreadyExistsCheck[] = "('" . prep_save($thisRow["accounttype"], 25) . "',
420  " . prep_save(intval($thisRow["certnumber"])) . ", 'D', $kendoId)";
421  $kendoId++;
422  }
423  }
424  if (HCU_array_key_exists("loan", $subaccountInfo)) {
425  foreach($subaccountInfo["loan"] as $thisRow) {
426  $thisRow["kendoId"] = $kendoId;
427  $thisRow["recordtype"] = "L";
428  $thisRow["isDeposit"] = false;
429  $thisRow["accounttype"] = $thisRow["loannumber"];
430  $thisRow["certnumber"] = 0;
431 
432  $canDeposit = !HCU_array_key_exists("may_payment", $thisRow) ? false : $thisRow["may_payment"];
433  $canWithdraw = !HCU_array_key_exists("may_addon", $thisRow) ? false : $thisRow["may_addon"];
434  $thisRow["canIntDeposit"] = $canDeposit;
435  $thisRow["canExtDeposit"] = $canDeposit;
436  $thisRow["canIntWithdraw"] = $canWithdraw;
437  $thisRow["canExtWithdraw"] = $canWithdraw;
438 
439  // Also add sort here.
440  $strposAt = strpos($thisRow["accounttype"], "@");
441  $permType = 0;
442  $permAccount = "000";
443  if ($strposAt !== false) {
444  $permType = 1;
445  $permAccount = substr($thisRow["accounttype"], $strposAt + 1);
446  }
447  $thisRow["perm_account_sort"] = $permAccount;
448  $thisRow["perm_type_sort"] = $permType;
449 
450  unset($thisRow["may_payment"]);
451  unset($thisRow["deposittype"]); // Find no use for this here.
452  unset($thisRow["may_addon"]);
453  unset($thisRow["loannumber"]);
454  $theSubaccountInfo[] = $thisRow;
455 
456  $alreadyExistsCheck[] = "('" . prep_save($thisRow["accounttype"], 25) . "',
457  " . prep_save(intval($thisRow["certnumber"])) . ", 'L', $kendoId)";
458  $kendoId++;
459  }
460  }
461  /* DO NOT PROCESS XAC if the CU is setup with 'Create Access Control records from XAC' on Home Banking Screen
462  * under this situation we will not be adding the XAC records to useraccounts - The admin may need to add them as separate accounts
463  * Otherwise, if the user is setup with "ACCESS" rights they will get the Cross Accounts as separate Accounts under Access Control
464  * the next time they access the Transfer screen.
465  */
466  if (HCU_array_key_exists("xa", $subaccountInfo) && (GetFlagsetValue("CU3_CREATE_ACCESS_CONTROL_FROM_XAC") & $flagset3) == 0 ) {
467  foreach($subaccountInfo["xa"] as $thisRow) {
468  $isDeposit = $thisRow["deposittype"] !== "L";
469 
470  // The only available option is the first column: internal deposit/payment.
471  $thisRow["kendoId"] = $kendoId;
472  $thisRow["isDeposit"] = $isDeposit;
473  $thisRow["canIntDeposit"] = true;
474  $thisRow["canExtDeposit"] = false;
475  $thisRow["canIntWithdraw"] = false;
476  $thisRow["canExtWithdraw"] = false;
477 
478  $thisRow["certnumber"] = 0;
479  $thisRow["accounttype"] .= "#" . $thisRow["tomember"];
480  $thisRow["recordtype"] = $isDeposit ? "T" : "P";
481 
482  // Also add sort here.
483  $thisRow["perm_account_sort"] = $thisRow["tomember"];
484  $thisRow["perm_type_sort"] = 2;
485 
486  $theSubaccountInfo[] = $thisRow;
487 
488  $alreadyExistsCheck[] = "('" . prep_save($thisRow["accounttype"], 25) . "',
489  " . intval($thisRow["certnumber"]) . ", '" . $thisRow["recordtype"] . "', $kendoId)";
490  $kendoId++;
491  }
492  }
493 
494  if (count($alreadyExistsCheck) > 0) {
495  $weedOutThese = array();
496  $sql = "select t.kendoid from ${Cu}useraccounts ua
497  inner join (values " . implode(",", $alreadyExistsCheck) . ") as t(accounttype, certnumber, recordtype, kendoid)
498  on ua.accounttype = t.accounttype and ua.certnumber = t.certnumber and ua.recordtype = t.recordtype
499  and ua.user_id = " . prep_save(intval($userId)) . " and ua.accountnumber = '" . prep_save($accountnumber, 12) . "'";
500  $sth = db_query($sql, $dbh);
501 
502  if (!$sth) {
503  throw new exception("check query failed.", 4);
504  }
505  for($i = 0; $row = db_fetch_row($sth, $i); $i++) {
506  $weedOutThese[] = intval($row[0]);
507  }
508 
509  $theOfficialSubaccountInfo = array();
510  foreach($theSubaccountInfo as $info) {
511  if (!in_array($info["kendoId"], $weedOutThese)) {
512  $theOfficialSubaccountInfo[] = $info;
513  }
514  }
515  } else {
516  $theOfficialSubaccountInfo = $theSubaccountInfo;
517  }
518 
519  } catch(exception $e) {
520  return array("error" => array($e->getMessage()), "code" => $e->getCode());
521  }
522  return array("error" => array(), "code" => 0, "accountInfo" => $theAccountInfo, "subaccountInfo" => $theOfficialSubaccountInfo);
523 }
524 
525 /**
526  * function CreateSubaccounts($pEnv, $subaccounts, $accountnumber, $latestKendoid)
527  * This will create the subaccounts after the account is found and one or more subaccounts are selected.
528  *
529  * @param $pEnv -- the environment
530  * @param $subaccounts -- an JSON encoded string from the subaccount grid.
531  * @param $accountnumber -- the account number
532  * @param $latestKendoid -- the latest kendoId
533  *
534  * @return $error -- zero count or the first error found
535  * @return $code -- zero if successful
536  * @return $newAccounts -- if it is needed to add another account, then it will show up here.
537  * Needed to refresh the grids.
538  * @return $accountEncryption -- the payload needed for the account link
539  * (if primary account is changed)
540  * @return $newSubaccounts -- All subaccounts added
541  * @return $setPrimaryAccount -- if the primary account was changed
542  * @return $primaryAccount -- the primary account if changed
543  * @return $dontShowAddNewAccount -- if true, hide the add new account button
544  * @return array("error" => zero or the first error found, "code" => zero if successful
545  */
546 function CreateSubaccounts($pEnv, $subaccounts, $accountnumber, $latestKendoid) {
547  $dontShowAddNewAccount = false;
548 
549  try {
550 
551  $allowZeroes = $pEnv["allowZeroes"];
552  $dbh = $pEnv["dbh"];
553  $userId = $pEnv["userId"];
554  $Cn = $pEnv["Cn"];
555  $Cu = $pEnv["Cu"];
556  $disallowMultipleAccounts = $pEnv["disallowMultipleAccounts"];
557 
558  // If don't allow leading zeroes, strip out the leading zeroes.
559  if (!$allowZeroes) {
560  $accountnumber = preg_replace('/^0+/', '', trim($accountnumber));
561  } else {
562  $accountnumber = trim($accountnumber);
563  }
564 
565  if (preg_match('/\D/', $accountnumber) === 1) {
566  throw new exception("Account number must be a number.", 28);
567  }
568  if ($subaccounts == "") {
569  throw new exception("No subaccounts found.", 1);
570  }
571  $subaccounts = hcu_JsonDecode($subaccounts);
572  if (!is_array($subaccounts) || count($subaccounts) == 0) {
573  throw new exception("No subaccounts found.", 2);
574  }
575 
576  // Check if primary user and account record isn't already created.
577  // this cose was moveabove the foreach loop to get the isGroupPrimary variable
578  // the variable is no used to set the $newsubAccounts permissions based in this variable
579  // permissions are set to the value of the isGroupPrimary field.
580  $sql = "select u.is_group_primary, ma.accountnumber is null, mar.user_id is null
581  from ${Cu}user u
582  left join ${Cu}memberacct ma on trim(ma.accountnumber) = '" . prep_save($accountnumber, 12) . "'
583  left join ${Cu}memberacctrights mar on u.user_id = mar.user_id and mar.whichright = 'ACCESS'
584  and trim(mar.accountnumber) = '" . prep_save($accountnumber, 12) . "'
585  where u.user_id = " . prep_save(intval($userId));
586  $sth = db_query($sql, $dbh);
587  if (!$sth) {
588  throw new exception("Primary check query failed.", 8);
589  }
590  $row = db_fetch_row($sth);
591  $isPrimaryUser = trim($row[0]) == "t";
592  $createMa = $isPrimaryUser && trim($row[1]) == "t";
593  $createAccess = $isPrimaryUser && trim($row[2]) == "t";
594 
595  if ($disallowMultipleAccounts) {
596  $sql = "select accountnumber, count(*) as count
597  from ${Cu}useraccounts
598  where user_id = " . prep_save(intval($userId)) . "
599  group by accountnumber";
600  $sth = db_query($sql, $dbh);
601  if (!$sth) {
602  throw new exception("Found query failed.", 29);
603  }
604  $results = db_fetch_all($sth);
605  $hasThisAccount = false;
606  $hasOtherAccounts = false;
607  if ($results !== false) {
608  foreach($results as $result) {
609  trim($result["accountnumber"]) == $accountnumber ? $hasThisAccount = $hasThisAccount || $result["count"] > 0
610  : $hasOtherAccounts = $hasOtherAccounts || $result["count"] > 0;
611  }
612  }
613 
614  if ($hasOtherAccounts) {
615  throw new exception ("Cannot add multiple accounts.", 30);
616  }
617  }
618 
619  // grab the highest display_order value for current subaccounts
620  // this will be used to set the display order for the new/updated
621  // subaccounts.
622  $sql = "select max(display_order) from {$Cu}useraccounts where user_id = 1";
623  $sth = db_query($sql, $dbh);
624  if (!$sth) {
625  throw new exception("display order query failed.", 9);
626  }
627  $row = db_fetch_row($sth);
628  $displayOrder = intval($row[0]);
629 
630  $createRecords = array();
631  $memberRecords = array();
632  $newSubaccounts = array();
633  $kendoid = $latestKendoid;
634  foreach($subaccounts as $subaccount) {
635  // increment display order to new records
636  // only increment if the max is greater than 0
637  if ($displayOrder > 0) {
638  $displayOrder ++;
639  }
640 
641  if (!HCU_array_key_exists("recordtype", $subaccount) || !HCU_array_key_exists("accounttype", $subaccount)
642  || !HCU_array_key_exists("certnumber", $subaccount)) {
643  throw new exception("Missing a required field.", 4);
644  }
645 
646  if (!in_array($subaccount["recordtype"], array("D", "L", "T", "P"))) {
647  throw new exception("Recordtype is unrecognized.", 13);
648  }
649 
650  $isCrossAccount = in_array($subaccount["recordtype"], array("T", "P"));
651 
652  $dontIntRestrictDeposit = HCU_array_key_exists("canIntDeposit", $subaccount) ? $subaccount["canIntDeposit"] : ($isPrimaryUser ? false : true);
653  $dontExtRestrictDeposit = HCU_array_key_exists("canExtDeposit", $subaccount) ? $subaccount["canExtDeposit"] : ($isPrimaryUser ? false : true);
654  $dontIntRestrictWithdraw = HCU_array_key_exists("canExtWithdraw", $subaccount) ? $subaccount["canIntWithdraw"] : ($isPrimaryUser ? false : true);
655  $dontExtRestrictWithdraw = HCU_array_key_exists("canExtWithdraw", $subaccount) ? $subaccount["canExtWithdraw"] : ($isPrimaryUser ? false : true);
656  $canIntDeposit = $isPrimaryUser ? $dontIntRestrictDeposit : false;
657  $canExtDeposit = $isPrimaryUser ? $dontExtRestrictDeposit : false;
658  $canIntWithdraw = $isPrimaryUser ? $dontIntRestrictWithdraw : false;
659  $canExtWithdraw = $isPrimaryUser ? $dontExtRestrictWithdraw : false;
660 
661  $canView = $isPrimaryUser && !$isCrossAccount;
662 
663  // If Loan accounts, do not allow external transfers
664  if ($subaccount["recordtype"] == 'L') {
665  $canExtWithdraw = false;
666  $dontExtRestrictWithdraw = false;
667  }
668 
669  // default the permissions based on this user is a group primary owner
670  $createRecords[] = array(
671  "_action" => "create", "user_id" => $userId,
672  "accountnumber" => $accountnumber, "accounttype" => $subaccount["accounttype"],
673  "certnumber" => intval($subaccount["certnumber"]), "display_name" => "",
674  "ext_deposit" => $canExtDeposit, "ext_withdraw" => $canExtWithdraw,
675  "int_deposit" => $canIntDeposit, "int_withdraw" => $canIntWithdraw,
676  "view_transactions" => $canView, "view_balances" => $canView,
677  "recordtype" => $subaccount["recordtype"],
678  "display_order" => $displayOrder);
679 
680  // Add new sort variables
681  $permAccount = "000";
682  $permType = 0;
683  $strposAt = strpos($subaccount["accounttype"], "@");
684  $strposHash = strpos($subaccount["accounttype"], "#");
685  if ( $strposAt !== false) {
686  $permAccount = substr($subaccount["accounttype"], $strposAt + 1);
687  $permType = 1;
688  } else if ( $strposHash !== false) {
689  $permAccount = substr($subaccount["accounttype"], $strposHash + 1);
690  $permType = 2;
691  }
692 
693  // For adding to the subaccount grid after being added.
694  $newSubaccounts[] = array(
695  "accountnumber" => $accountnumber,
696  "accounttype" => $subaccount["accounttype"],
697  "certnumber" => intval($subaccount["certnumber"]),
698  "display_name" => "",
699  "description" => $subaccount["description"],
700  "ext_deposit" => $canExtDeposit,
701  "ext_withdraw" => $canExtWithdraw,
702  "restrictExtDeposit" => !$dontExtRestrictDeposit,
703  "restrictIntDeposit" => !$dontIntRestrictDeposit,
704  "int_deposit" => $canIntDeposit,
705  "int_withdraw" => $canIntWithdraw,
706  "restrictExtWithdraw" => !$dontExtRestrictWithdraw,
707  "restrictIntWithdraw" => !$dontIntRestrictWithdraw,
708  "view_transactions" => $canView,
709  "view_balances" => $canView,
710  "restrictViewBalances" => $isCrossAccount,
711  "restrictViewTransactions" => $isCrossAccount || !$canView,
712  "recordtype" => $subaccount["recordtype"],
713  "recordTypeFilter" => in_array($subaccount["recordtype"], array("D", "T")) ? "D" : "L",
714  "display_order" => $displayOrder,
715  "perm_account_sort" => $permAccount,
716  "perm_type_sort" => $permType,
717  "kendoid" => $kendoid ++);
718  }
719  $createRecords = array("useraccounts" => $createRecords);
720 
721  $sql = "select email from cuadminusers
722  where user_name = '" . prep_save($Cn, 50) . "' and cu = '" . prep_save($Cu, 10) . "'";
723  $sth = db_query($sql, $dbh);
724  if (!$sth) {
725  throw new exception("email query failed.", 5);
726  }
727  $email = db_fetch_row($sth)[0];
728 
729  $context = "admin";
730  $script = "userSupportAccessControl.prg";
731  $addr = trim($_SERVER["REMOTE_ADDR"]);
732  $vars = array("cu" => $Cu);
733 
734  $newAccounts = array();
735 
736  if (!db_work($dbh, HOMECU_WORK_BEGIN)) {
737  throw new exception("begin work query failed!", 10);
738  }
739 
740  $results = DataUserTableUpdate($dbh, $vars, null, $createRecords, $userId, "UA_ADD", $context, $script,
741  "A", "User Accounts Add", $Cn, $email, $addr);
742 
743  if ($results === false) {
744  throw new exception("Adding failed.", 106);
745  }
746 
747  $dontShowAddNewAccount = $disallowMultipleAccounts && !$hasThisAccount;
748  // When one or more subaccounts are added, check to see if this is in a new account. If it is, remove button.
749 
750  // This will only need to be added for the primary user.
751  if ($createMa) {
752  $memberRecords = array("memberacct" => array(array("_action" => "create", "accountnumber" => $accountnumber, "primary_user" => $userId)));
753  $results = DataUserTableUpdate($dbh, $vars, null, $memberRecords, $userId, "UM_ADD",
754  $context, $script, "A", "User Member Add", $Cn, $email, $addr);
755  if ($results === false) {
756  throw new exception("Adding failed.", 107);
757  }
758  }
759 
760  if ($createAccess) {
761  $official = array("memberacctrights" => array(
762  array("_action" => "create", "accountnumber" => $accountnumber, "user_id" => $userId, "whichright" => "ACCESS"),
763  array("_action" => "create", "accountnumber" => $accountnumber, "user_id" => $userId, "whichright" => "RDC", "platform" => '["D","A"]'),
764  array("_action" => "create", "accountnumber" => $accountnumber, "user_id" => $userId, "whichright" => "BP", "platform" => '["D","A"]'),
765  array("_action" => "create", "accountnumber" => $accountnumber, "user_id" => $userId, "whichright" => "ES", "platform" => '["D","A"]')
766  ));
767 
768  $results = DataUserTableUpdate($dbh, $vars, null, $official, $userId, "ACCESS_ADD", $context, $script,
769  "A", "Primary User Access Add", $Cn, $email, $addr);
770  if ( $results === false) {
771  throw new exception("Adding failed.", 109);
772  }
773 
774  $newAccounts[] = array("accountnumber" => $accountnumber, "access" => true, "bpApp" => true, "bpDsk" => true, "esApp" => true, "esDsk" => true,
775  "rdcApp" => true, "rdcDsk" => true);
776  }
777 
778  if (!db_work($dbh, HOMECU_WORK_COMMIT)) {
779  throw new exception("commit query failed.", 111);
780  }
781  } catch(exception $e) {
782  if ($e->getCode() >= 100) {
783  db_work($dbh, HOMECU_WORK_ROLLBACK);
784  }
785  return array("error" => array($e->getMessage()), "code" => $e->getCode());
786  }
787  return array("error" => array(), "code" => 0, "newAccounts" => $newAccounts, "newSubaccounts" => $newSubaccounts, "latestKendoid" => $latestKendoid,
788  "dontShowAddNewAccount" => $dontShowAddNewAccount);
789 }
790 
791 /**
792  * function ExpandSettings(&$row, $key)
793  * Expands the settings from what is in the database to what is needed for the grid.
794  *
795  * @param $row -- the row to expand
796  * @param $key -- the key to expand
797  */
798 function ExpandSettings(&$row, $key) {
799  if ($row[$key] != null) {
800  $decoded = hcu_JsonDecode($row[$key]);
801  if (!is_array($decoded)) {
802  throw new exception("$key not formatted correctly.", 2);
803  }
804 
805  $row["${key}Dsk"] = in_array("D", $decoded);
806  $row["${key}App"] = in_array("A", $decoded);
807  unset($row[$key]);
808  } else {
809  $row["${key}Dsk"] = false;
810  $row["${key}App"] = false;
811  }
812 
813  unset($row[$key]);
814 }
815 
816 /**
817  * function ReadAccessControl($pEnv)
818  * This function reads the access control for the userId.
819  *
820  * @param $pEnv -- the environment
821  *
822  * @return $error -- empty array or the first error encountered
823  * @return $code -- nonzero if there is an error
824  * @return $accountData -- All accounts found that the user has access to
825  * @return $subaccountData -- All subaccounts found that the user has access to
826  * @return $isPrimary -- whether the user is primary
827  * @return $dontShowAddNewAccount -- if true, hide the butto
828  */
829 function ReadAccessControl($pEnv) {
830  try {
831 
832  $dbh = $pEnv["dbh"];
833  $Cu = $pEnv["Cu"];
834  $Cn = $pEnv["Cn"];
835  $userId = $pEnv["userId"];
836  $allowZeroes = $pEnv["allowZeroes"];
837  $disallowMultipleAccounts = $pEnv["disallowMultipleAccounts"];
838 
839  // Get account list. HAVE to get that from the primary user.
840  $sql = "select mm.accountnumber, pu.user_id from
841  (select p.user_id, p.group_id from ${Cu}user p
842  inner join ${Cu}user u on p.group_id = u.group_id and p.is_group_primary and u.user_id = " . prep_save(intval($userId)) . " limit 1) as pu
843  left join (select distinct trim(accountnumber), user_id from ${Cu}useraccounts) as mm(accountnumber, user_id) on pu.user_id = mm.user_id";
844 
845  $sth = db_query($sql, $dbh);
846 
847  if (!$sth) {
848  throw new exception("Access control list failed.", 3);
849  }
850  $isPrimary = false;
851 
852  $accounts = array();
853  $first = true;
854 
855  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
856  if ($first) {
857  $isPrimary = $row["user_id"] == $userId;
858  $first = false;
859  }
860  if (!is_null($row["accountnumber"])) {
861  $accountnumber = $row["accountnumber"];
862  if (!$allowZeroes) {
863  $accountnumber = preg_replace('/^0+/', '', trim($accountnumber));
864  }
865  $accounts[] = trim(prep_save($accountnumber, 12));
866  }
867  }
868 
869  $dontShowAddNewAccount = $disallowMultipleAccounts && count($accounts) > 0;
870 
871  $accountData = array();
872  $newAccountData = array();
873  $subaccountData = array();
874  if (count($accounts) > 0) {
875  // Then once the list of the accounts is retrieved from the primary user, then the rights are retrieved from the actual user.
876  $sql = "with rghts as (select trim(accountnumber) as accountnumber, whichright, platform, allowed
877  from ${Cu}memberacctrights where user_id = $userId
878  and whichright in ('ACCESS', 'RDC', 'BP', 'ES'))
879  select ma.accountnumber, access.allowed as access, rdc.platform as rdc, bp.platform as bp,
880  es.platform as es from (values ('" . implode("'),('", $accounts) . "')) as ma(accountnumber)
881  inner join ${Cu}user u on u.user_id = " . prep_save(intval($userId)) . "
882  left join rghts access on ma.accountnumber = trim(access.accountnumber) and access.whichright = 'ACCESS'
883  left join rghts rdc on ma.accountnumber = rdc.accountnumber and rdc.whichright = 'RDC'
884  left join rghts bp on ma.accountnumber = bp.accountnumber and bp.whichright = 'BP'
885  left join rghts es on ma.accountnumber = es.accountnumber and es.whichright = 'ES'";
886 
887  $sth = db_query($sql, $dbh);
888 
889  if (!$sth) {
890  throw new exception("Right query failed.", 1);
891  }
892 
893  $accounts = array();
894  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
895  $row["access"] = $row["access"] == "t";
896  ExpandSettings($row, "rdc");
897  ExpandSettings($row, "bp");
898  ExpandSettings($row, "es");
899  $accountData[] = $row;
900  $accounts[] = trim(prep_save($row["accountnumber"], 12));
901  }
902 
903  // Then once the list of the accounts is retrieved from the primary user, then the rights for the subaccounts are retrieved from the actual user.
904  $subqueryUA = "select accountnumber, display_name, ext_withdraw, display_order, view_balances, trim(accounttype) as accounttype, certnumber,
905  trim(recordtype) as recordtype, view_transactions, int_deposit, int_withdraw, ext_deposit,
906  certnumber || trim(recordtype) || trim(accountnumber) || trim(accounttype) as key,
907  case when position('@' in accounttype) <> 0 then 1
908  when position('#' in accounttype) <> 0 then 2
909  else 0 end as perm_type_sort,
910  case when position('@' in accounttype) <> 0 then split_part(accounttype, '@', 2)
911  when position('#' in accounttype) <> 0 then split_part(accounttype, '#', 2)
912  else '000' end as perm_account_sort
913  from ${Cu}useraccounts
914  where trim(accountnumber) in ('" . implode("','", $accounts) . "') and user_id = $userId and trim(recordtype) in ('D', 'L', 'T', 'P')";
915 
916  $subqueryALXB = "select certnumber || 'D' || trim(accountnumber) || trim(accounttype), trim(description),
917  may_deposit, may_withdraw
918  from ${Cu}accountbalance
919  union all
920  select '0' || 'T' || trim(accountnumber) || trim(accounttype) || '#' || trim(tomember) as key,
921  trim(description), true, false
922  from ${Cu}crossaccounts where deposittype <> 'L'
923  union all
924  select '0' || 'L' || trim(accountnumber) || trim(loannumber) as key,
925  trim(description), may_payment, may_addon
926  from ${Cu}loanbalance
927  union all
928  select '0' || 'P' || trim(accountnumber) || trim(accounttype) || '#' || trim(tomember) as key,
929  trim(description), false, false
930  from ${Cu}crossaccounts where deposittype = 'L'";
931 
932  $sql = "select ua.*, alxb.description, alxb.key as rec_exists, alxb.allow_deposit, alxb.allow_withdraw
933  from ($subqueryUA) as ua
934  left join ($subqueryALXB) as alxb(key, description, allow_deposit, allow_withdraw) on ua.key = alxb.key
935  order by ua.accountnumber, ua.perm_account_sort, ua.perm_type_sort, ua.display_order";
936 
937  $sth = db_query($sql, $dbh);
938 
939  if (!$sth) {
940  throw new exception("Sub-account query failed.", 2);
941  }
942 
943  $usedAccounts = array();
944  $correctLimit = array(); // If there is a balance record and the permissions are greater than what is in the database, correct it on page load.
945  $kendoid = 1;
946  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
947  $row["kendoid"] = $kendoid++;
948  $row["view_balances"] = is_null($row["view_balances"]) ? false : trim($row["view_balances"]) == "t";
949  $row["view_transactions"] = is_null($row["view_transactions"]) ? false : trim($row["view_transactions"]) == "t";
950  $row["int_deposit"] = is_null($row["int_deposit"]) ? false : trim($row["int_deposit"]) == "t";
951  $row["int_withdraw"] = is_null($row["int_withdraw"]) ? false : trim($row["int_withdraw"]) == "t";
952  $row["ext_deposit"] = is_null($row["ext_deposit"]) ? false : trim($row["ext_deposit"]) == "t";
953  $row["ext_withdraw"] = is_null($row["ext_withdraw"]) ? false : trim($row["ext_withdraw"]) == "t";
954 
955  $row["description"] = isset($row["description"]) ? trim($row["description"]) : "";
956  $row["display_name"] = isset($row["display_name"]) ? trim($row["display_name"]) : "";
957  $row["display_name"] = $row["display_name"] == "" || $row["display_name"] == $row["description"] ? "" : $row["display_name"];
958  $row["accountnumber"] = isset($row["accountnumber"]) ? trim($row["accountnumber"]) : "";
959 
960  // Set the defaults for the permissions. Otherwise, it shows as "undefined" in the grid. "Undefined" in the grid works but this is clearer.
961  $row["restrictViewBalances"] = false;
962  $row["restrictViewTransactions"] = !$row["view_balances"];
963  $row["restrictIntDeposit"] = false;
964  $row["restrictExtDeposit"] = false;
965  $row["restrictIntWithdraw"] = false;
966  $row["restrictExtWithdraw"] = false;
967 
968  // If I have "corrections" for the other columns, then probably need them for these columns as well.
969  if ($row["restrictViewTransactions"] && $row["view_transactions"]) {
970  $correctLimitRow["view_transactions"] = false;
971  $row["ext_withdraw"] = false;
972  }
973 
974  if ($row["restrictViewBalances"] && $row["view_balances"]) {
975  $correctLimitRow["view_balances"] = false;
976  $row["view_balances"] = false;
977  }
978 
979  // If Loan accounts, do not allow external transfers
980  if (in_array($row["recordtype"], array("L"))) {
981  $row["restrictExtWithdraw"] = true;
982  }
983 
984  // If Cross Accounts, only the int_deposit is available, otherwise follow allow_deposit, allow_withdraw.
985  // This is outside of the rec_exists for the case when a cross account is added to admin but the user hasn't logged in yet.
986  // (Cross account record doesn't exist.)
987  // In this case, the restrictions still need to prevent changing. The only information needed to do this is the recordtype.
988  if (in_array($row["recordtype"], array("T", "P"))) {
989  $row["restrictIntDeposit"] = false;
990  $row["restrictExtDeposit"] = true;
991  $row["restrictIntWithdraw"] = true;
992  $row["restrictExtWithdraw"] = true;
993  $row["restrictViewBalances"] = true;
994  $row["restrictViewTransactions"] = true;
995 
996  // View History and View Balances should always be false for Cross Accounts.
997  // If they are found true, then we need to correct the row like it is done for D and L.
998  if ($row["view_balances"]) {
999  $correctLimitRow["view_balances"] = false;
1000  $row["view_balances"] = false;
1001  }
1002 
1003  if ($row["view_transactions"]) {
1004  $correctLimitRow["view_transactions"] = false;
1005  $row["view_transactions"] = false;
1006  }
1007  }
1008 
1009  if (isset($row["rec_exists"])) {
1010  if (in_array($row["recordtype"], array("D", "L"))) {
1011  $restrictDeposit = !isset($row["allow_deposit"]) ? false : trim($row["allow_deposit"]) != "t";
1012  $restrictWithdraw = !isset($row["allow_withdraw"]) ? false : trim($row["allow_withdraw"]) != "t";
1013  $row["restrictIntDeposit"] = $restrictDeposit;
1014  $row["restrictExtDeposit"] = $restrictDeposit;
1015  $row["restrictIntWithdraw"] = $restrictWithdraw;
1016  $row["restrictExtWithdraw"] = $restrictWithdraw;
1017  }
1018 
1019  // If Loan accounts, do not allow external transfers
1020  if (in_array($row["recordtype"], array("L"))) {
1021  $row["restrictExtWithdraw"] = true;
1022  }
1023 
1024  $correctLimitRowA = array("user_id" => $userId, "accountnumber" => $row["accountnumber"], "accounttype" => $row["accounttype"],
1025  "certnumber" => $row["certnumber"], "recordtype" => $row["recordtype"], "_action" => "update");
1026 
1027  $correctLimitRow = array();
1028  if ($row["restrictIntDeposit"] && $row["int_deposit"]) {
1029  $correctLimitRow["int_deposit"] = false;
1030  $row["int_deposit"] = false;
1031  }
1032 
1033  if ($row["restrictExtDeposit"] && $row["ext_deposit"]) {
1034  $correctLimitRow["ext_deposit"] = false;
1035  $row["ext_deposit"] = false;
1036  }
1037 
1038  if ($row["restrictIntWithdraw"] && $row["int_withdraw"]) {
1039  $correctLimitRow["int_withdraw"] = false;
1040  $row["int_withdraw"] = false;
1041  }
1042 
1043  if ($row["restrictExtWithdraw"] && $row["ext_withdraw"]) {
1044  $correctLimitRow["ext_withdraw"] = false;
1045  $row["ext_withdraw"] = false;
1046  }
1047 
1048  if (count($correctLimitRow) > 0) {
1049  $correctLimit[] = array_merge($correctLimitRowA, $correctLimitRow);
1050  }
1051  }
1052 
1053 
1054  // Actual grid doesn't (at this time) care if record is a cross account or not.
1055  $row["recordTypeFilter"] = $row["recordtype"] == "T" ? "D" : ($row["recordtype"] == "P" ? "L" : $row["recordtype"]);
1056 
1057  // Remove unused columns.
1058  unset($row["rec_exists"]);
1059  unset($row["key"]);
1060 
1061  $subaccountData[] = $row;
1062 
1063  }
1064 
1065  if (count($correctLimit) > 0) {
1066  $sql = "select email from cuadminusers where user_name = '" . prep_save($Cn, 50) . "' and cu = '" . prep_save($Cu, 10) . "'";
1067  $sth = db_query($sql, $dbh);
1068  if (!$sth) {
1069  throw new exception("email query failed.", 4);
1070  }
1071  $email = db_fetch_row($sth)[0];
1072 
1073  $context = "admin";
1074  $script = "userSupportAccessControl.prg";
1075  $addr = trim($_SERVER["REMOTE_ADDR"]);
1076  $vars = array("cu" => $Cu);
1077 
1078  $results = DataUserTableUpdate($dbh, $vars, null, array("useraccounts" => $correctLimit), $userId, "USERA_UPD",
1079  $context, $script, "A", "Correct Restrictions", $Cn, $email, $addr);
1080 
1081  if ($results === false) {
1082  throw new exception("Correct query failed.", 3);
1083  }
1084  }
1085  }
1086 
1087  $returnArray = array("error" => array(), "code" => 0, "accountData" => $accountData, "subaccountData" => $subaccountData, "isPrimary" => $isPrimary,
1088  "latestKendoid" => isset($kendoid) ? $kendoid : 1, "dontShowAddNewAccount" => $dontShowAddNewAccount);
1089  } catch(exception $e) {
1090  $returnArray = array("error" => array($e->getMessage()), "code" => $e->getCode());
1091  }
1092  return $returnArray;
1093 }
1094 
1095 /**
1096  * function SaveAccountsAndSubaccounts($pEnv, $accounts, $subaccounts)
1097  * This will save everything.
1098  * It was two separate data calls but it turns out that it is hard to coordinate separate data calls.
1099  *
1100  * @param $pEnv -- the environment
1101  * @param $accounts -- the accounts to save (from the grid. The ones that are changed)
1102  * @param $subaccounts -- the subaccounts to save (from the grid. The ones that are changed)
1103  *
1104  * @return $error -- an empty array or the first error found
1105  * @return $code -- nonzero if there is at least one error
1106  */
1107 function SaveAccountsAndSubaccounts($pEnv, $accounts, $subaccounts) {
1108  try {
1109  $dbh = $pEnv["dbh"];
1110  $Cu = $pEnv["Cu"];
1111  $Cn = $pEnv["Cn"];
1112  $userId = $pEnv["userId"];
1113 
1114  $full = array();
1115  $platforms = array();
1116  $codes = array();
1117  $accounts = $accounts == null ? "" : trim($accounts);
1118  if ($accounts != "" && $accounts != "[]") {
1119  $accounts = hcu_JsonDecode($accounts);
1120  if (!is_array($accounts) || count($accounts) == 0) {
1121  throw new exception("Accounts aren't encoded correctly.", 1);
1122  }
1123  foreach($accounts as $account) {
1124  if (!isset($account["accountnumber"])) {
1125  throw new exception("Account requires a number.", 2);
1126  }
1127  if (isset($account["access"])) {
1128  $sql = "select 'FOUND' from ${Cu}memberacctrights
1129  where user_id = " . prep_save(intval($userId)) . " and accountnumber = '" . prep_save($account["accountnumber"], 12) . "'
1130  and whichright = 'ACCESS'";
1131  $sth = db_query($sql, $dbh);
1132  if (!$sth) {
1133  throw new exception ("Found SQL failed.", 13);
1134  }
1135  $action = db_num_rows($sth) > 0 ? "update" : "create";
1136  $full[] = array("_action" => $action, "whichright" => "ACCESS", "user_id" => $userId, "accountnumber" => $account["accountnumber"],
1137  "allowed" => $account["access"]);
1138  }
1139  ProcessSettings($account, "es", $platforms, $codes);
1140  ProcessSettings($account, "rdc", $platforms, $codes);
1141  ProcessSettings($account, "bp", $platforms, $codes);
1142  }
1143 
1144  if (count($codes) > 0) {
1145  $sql = "select v.code, v.accountnumber, mar.user_id as exists
1146  from (values " . implode(",", $codes) . ") as v (code, accountnumber)
1147  left join ${Cu}memberacctrights mar on v.code = mar.whichright
1148  and v.accountnumber = mar.accountnumber and mar.user_id = " . prep_save(intval($userId));
1149  $sth = db_query($sql, $dbh);
1150  if (!$sth) {
1151  throw new exception("Verify SQL failed.", 3);
1152  }
1153 
1154  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
1155  $exists = $row["exists"] != null && trim($row["exists"]) != "";
1156  $accountnumber = $row["accountnumber"] == null ? "" : trim($row["accountnumber"]);
1157  $code = $row["code"] == null ? "" : trim($row["code"]);
1158  $platform = $platforms[$accountnumber][$code];
1159  $record = array("whichright" => $code, "user_id" => $userId, "accountnumber" => $accountnumber, "platform" => HCU_JsonEncode($platform));
1160  if (!$exists) {
1161  if (count($platform) > 0) {
1162  $record["_action"] = "create";
1163  $full[] = $record;
1164  }
1165  } else {
1166  if (count($platform) == 0) {
1167  $record["_action"] = "delete";
1168  unset($record["platform"]);
1169  $full[] = $record;
1170  } else {
1171  $record["_action"] = "update";
1172  $full[] = $record;
1173  }
1174  }
1175  }
1176  }
1177  }
1178 
1179  $subUpdates = array();
1180  $subaccounts = is_null($subaccounts) ? "" : trim($subaccounts);
1181  if ($subaccounts != "" && $subaccounts != "[]") {
1182  $subaccounts = hcu_JsonDecode($subaccounts);
1183  if (!is_array($subaccounts) || count($subaccounts) == 0) {
1184  throw new exception("Sub-account not formed correctly.", 8);
1185  }
1186  foreach($subaccounts as $row) {
1187  if (!isset($row["accounttype"]) || !isset($row["certnumber"]) || !isset($row["recordtype"]) || !isset($row["accountnumber"])) {
1188  throw new exception("Sub-account not formed correctly.", 9);
1189  }
1190  $row["_action"] = "update";
1191  $row["user_id"] = $userId;
1192  $subUpdates[] = $row;
1193  }
1194  }
1195 
1196  if (count($full) > 0 || count($subUpdates) > 0) {
1197  $sql = "select email from cuadminusers where user_name = '" . prep_save($Cn, 50) . "' and cu = '" . prep_save($Cu, 10) . "'";
1198  $sth = db_query($sql, $dbh);
1199  if (!$sth) {
1200  throw new exception("email query failed.", 4);
1201  }
1202  $email = db_fetch_row($sth)[0];
1203 
1204  $context = "admin";
1205  $script = "userSupportAccessControl.prg";
1206  $addr = trim($_SERVER["REMOTE_ADDR"]);
1207  $vars = array("cu" => $Cu);
1208 
1209  if (!db_work($dbh, HOMECU_WORK_BEGIN)) {
1210  throw new exception("Work begin query failed.", 12);
1211  }
1212 
1213  if (count($full) > 0) {
1214  $official = array("memberacctrights" => $full);
1215  $results = DataUserTableUpdate($dbh, $vars, null, $official, $userId, "MAR_CHG", $context, $script,
1216  "A", "Member Account Rights Change", $Cn, $email, $addr);
1217  if ( $results === false) {
1218  throw new exception("change failed.", 107);
1219  }
1220  }
1221 
1222  if (count($subUpdates) > 0) {
1223  $official = array("useraccounts" => $subUpdates);
1224 
1225  $results = DataUserTableUpdate($dbh, $vars, null, $official, $userId, "UA_UPDATE", $context, $script,
1226  "A", "User Accounts Update", $Cn, $email, $addr);
1227  if ( $results === false) {
1228  throw new exception("Sub Updating failed.", 110);
1229  }
1230  }
1231 
1232  if (!db_work($dbh, HOMECU_WORK_COMMIT)) {
1233  throw new exception("Work commit query failed.", 112);
1234  }
1235  }
1236  } catch(exception $e) {
1237  if ($e->getCode() >= 100) {
1238  db_work($dbh, HOMECU_WORK_ROLLBACK);
1239  }
1240  return array("error" => array($e->getMessage()), "code" => $e->getCode());
1241  }
1242  return array("error" => array(), "code" => 0);
1243 }
1244 
1245 /**
1246  * function processSettings($account, $setting, &$platforms, &$codes)
1247  * Convert grid values to what is in the database
1248  *
1249  * @param $account -- the account to process
1250  * @param $setting -- the control
1251  * @param $platforms -- build this array of "D", "A" per account and control.
1252  * @param $codes -- build this array for checking the database for existence.
1253  */
1254 function ProcessSettings($account, $setting, &$platforms, &$codes) {
1255  $setting = trim($setting);
1256  if (HCU_array_key_exists("${setting}Dsk", $account) && HCU_array_key_exists("${setting}App", $account)) {
1257  $platform = array();
1258  $account["${setting}Dsk"] && $platform[] = "D";
1259  $account["${setting}App"] && $platform[] = "A";
1260 
1261  $code = strtoupper($setting);
1262  $accountnumber = trim($account["accountnumber"]);
1263  if (!isset($platforms[$accountnumber])) {
1264  $platforms[$accountnumber] = array();
1265  }
1266  $platforms[$accountnumber][$code] = $platform;
1267  $codes[] = "('$code', '" . prep_save($accountnumber, 12) . "')";
1268  }
1269 }