Odyssey
aMemberPurge.prg
1 <?php
2 /**
3  * @package MemberHub
4  * @author Erin
5  *
6  * @uses admin member delete/purge
7  * * delete orphaned members
8  * * delete users from member by going to user hub
9  *
10  * @var string $sOperation: requested search action
11  */
12 
13 require_once("$admLibrary/aMemberSupport.i");
14 
15 try {
16  $admVars = array();
17  $admOk = array(
18  "operation" => array("filter" => FILTER_SANITIZE_STRING),
19  "payload" => array("filter" => FILTER_SANITIZE_STRING)
20  );
21  HCU_ImportVars($admVars, "MEMBER_PURGE", $admOk);
22 
23  $dOperation = isset($admVars["MEMBER_PURGE"]["operation"]) ? $admVars["MEMBER_PURGE"]["operation"] : null;
24  $dPayload = isset($admVars["MEMBER_PURGE"]["payload"]) ? $admVars["MEMBER_PURGE"]["payload"] : null;
25 
26  // decrypt payload only if there is one
27  // payload won't exist if operation is empty
28  // operation empty means just load card content
29  $dMember = $dPayload ? MemberDecrypt($SYSENV, $Cu, $dPayload) : null;
30 
31  // load context depending on payload existence.
32  $dContext = $dPayload ? MemberContext($SYSENV, $Cu, $dMember['member']) : MemberContext($SYSENV, $Cu);
33 
34  $aryResult = array();
35  $aryReply = array();
36 
37  switch ($dOperation) {
38  case "":
39  PrintMemberPurge();
40  break;
41  case "memberPurge":
42  header('Content-type: application/json');
43 
44  $mPurge = MemberPurge($SYSENV, $dbh, $dContext);
45  $aryResult['data']['member'] = $mPurge['member'];
46  $aryResult['info'] = $mPurge['message'];
47  MemberReply($aryResult, $aryReply, $dOperation);
48 
49  break;
50  default:
51  throw new Exception("Unknown server request: " . $dOperation);
52  break;
53  }
54 
55 
56 } catch (Exception $e) {
57  $aryReply['errors'][] = $e->getMessage();
58  $aryResult['data'] = array();
59  $aryResult['info'] = array();
60  MemberReply($aryResult, $aryReply, $dOperation);
61 }
62 
63 
64 /**
65  * Removing records from the following tables:
66  * {cu}accountbalance
67  * {cu}accounthistory
68  * {cu}loanbalance
69  * {cu}loanhistory
70  * {cu}crossaccounts
71  * {cu}memberacct
72  * {cu}memberacctrights
73  * {cu}transhdr
74  * {cu}transdtl
75  * {cu}holds
76  */
77 function MemberPurge($pEnv, $pDbh, $pContext) {
78 
79  $dHistory = MemberReadHistory($pEnv, $pDbh, $pContext);
80  $dValidateHistory = MemberValidateHistory($pEnv, $pContext, $dHistory);
81  $dDelete = MemberDeleteHistory($pEnv, $pDbh, $pContext, $dValidateHistory);
82 
83  $sqlReturn = array();
84  if ($dDelete['message'] == "Success") {
85  $sqlReturn['member'] = $pContext['m_account'];
86  $sqlReturn['message'] = "The following member account has been deleted successfully: " . $pContext['m_account'];
87  } else {
88  $pEnv['logger']->error(db_last_error());
89  throw new Exception("Failed to delete member account.");
90  }
91 
92  return $sqlReturn;
93 }
94 
95 function MemberReadHistory($pEnv, $pDbh, $pContext) {
96  $cuTable = $pContext['cu_table'];
97  $cuMember = $pContext['m_account'];
98 
99  $sqlReturn = array();
100  $sqlData = array();
101  //loan tables
102  $sqlColumns = "
103  DISTINCT ON (lb.loannumber) lb.loannumber AS a_type,
104  lb.accountnumber AS a_number,
105  lb.description AS a_desc,
106  'Loan' AS a_record";
107  $sqlSub = "
108  SELECT COUNT(*)
109  FROM {$cuTable}loanhistory lh
110  WHERE lh.accountnumber = '$cuMember'
111  AND lh.loannumber = lb.loannumber";
112  $sqlSelect = "
113  SELECT $sqlColumns, ($sqlSub) AS a_count
114  FROM {$cuTable}loanbalance lb
115  WHERE lb.accountnumber = '$cuMember'";
116  $sqlSelectRs = db_query($sqlSelect, $pDbh);
117  if (!$sqlSelectRs) {
118  $pEnv['logger']->error(db_last_error());
119  throw new Exception("Failed to read transaction history for loan accounts.");
120  }
121  $sqlData['loan'] = db_fetch_all($sqlSelectRs);
122 
123  //account tables
124  $sqlColumns = "
125  DISTINCT ON (ab.accounttype) ab.accounttype AS a_type,
126  ab.accountnumber AS a_number,
127  ab.description AS a_desc,
128  'Deposit' AS a_record";
129  $sqlSub = "
130  SELECT COUNT(*)
131  FROM {$cuTable}accounthistory ah
132  WHERE ah.accountnumber = '$cuMember'
133  AND ah.accounttype = ab.accounttype";
134  $sqlSelect = "
135  SELECT $sqlColumns, ($sqlSub) AS a_count
136  FROM {$cuTable}accountbalance ab
137  WHERE ab.accountnumber = '$cuMember'";
138  $sqlSelectRs = db_query($sqlSelect, $pDbh);
139  if (!$sqlSelectRs) {
140  $pEnv['logger']->error(db_last_error());
141  throw new Exception("Failed to read transaction history for deposit accounts.");
142  }
143  $sqlData['deposit'] = db_fetch_all($sqlSelectRs);
144 
145  //transaction tables
146  $sqlColumns = "
147  DISTINCT ON (tr.accounttype) tr.accounttype AS a_type,
148  tr.accountnumber AS a_number,
149  tr.memo AS a_desc,
150  'Transaction' AS a_record";
151  $sqlSub = "
152  SELECT COUNT(*)
153  FROM {$cuTable}transdtl td
154  WHERE td.transhdr_id = tr.id";
155  $sqlSelect = "
156  SELECT $sqlColumns, ($sqlSub) AS a_count
157  FROM {$cuTable}transhdr tr
158  WHERE tr.accountnumber = '$cuMember'";
159  $sqlSelectRs = db_query($sqlSelect, $pDbh);
160  if (!$sqlSelectRs) {
161  $pEnv['logger']->error(db_last_error());
162  throw new Exception("Failed to read transaction history for accounts.");
163  }
164  $sqlData['transactions'] = db_fetch_all($sqlSelectRs);
165 
166  //crossaccount table
167  $sqlColumns = "
168  DISTINCT ON (ca.accounttype) ca.accounttype AS a_type,
169  ca.accountnumber AS a_number,
170  ca.description AS a_desc,
171  'CrossAccount' AS a_record";
172  $sqlSub = "
173  SELECT COUNT(*)
174  FROM {$cuTable}crossaccounts
175  WHERE accountnumber = '$cuMember'";
176  $sqlSelect = "
177  SELECT $sqlColumns, ($sqlSub) AS a_count
178  FROM {$cuTable}crossaccounts ca
179  WHERE ca.accountnumber = '$cuMember'";
180  $sqlSelectRs = db_query($sqlSelect, $pDbh);
181  if (!$sqlSelectRs) {
182  $pEnv['logger']->error(db_last_error());
183  throw new Exception("Failed to read crossaccounts.");
184  }
185  $sqlData['crossaccounts'] = db_fetch_all($sqlSelectRs);
186 
187  //memberacct and memberacctrights tables
188  $sqlColumns = "
189  'NA' AS a_type,
190  ma.accountnumber AS a_number,
191  'NA' AS a_desc,
192  'MemberAccount' AS a_record";
193  $sqlSub = "
194  SELECT COUNT(*)
195  FROM {$cuTable}memberacctrights mr
196  WHERE mr.accountnumber = '$cuMember'";
197  $sqlSelect = "
198  SELECT $sqlColumns, ($sqlSub) AS a_count
199  FROM {$cuTable}memberacct ma
200  WHERE ma.accountnumber = '$cuMember'";
201  $sqlSelectRs = db_query($sqlSelect, $pDbh);
202  if (!$sqlSelectRs) {
203  $pEnv['logger']->error(db_last_error());
204  throw new Exception("Failed to read transaction history for deposit accounts.");
205  }
206  $sqlData['memberacct'] = db_fetch_all($sqlSelectRs);
207 
208  //holds table
209  $sqlColumns = "
210  DISTINCT ON (h.accounttype) h.accounttype AS a_type,
211  h.accountnumber AS a_number,
212  h.description AS a_desc,
213  'Holds' AS a_record";
214  $sqlSub = "
215  SELECT COUNT(*)
216  FROM {$cuTable}holds
217  WHERE accountnumber = '$cuMember'";
218  $sqlSelect = "
219  SELECT $sqlColumns, ($sqlSub) AS a_count
220  FROM {$cuTable}holds h
221  WHERE h.accountnumber = '$cuMember'";
222  $sqlSelectRs = db_query($sqlSelect, $pDbh);
223  if (!$sqlSelectRs) {
224  $pEnv['logger']->error(db_last_error());
225  throw new Exception("Failed to read holds.");
226  }
227  $sqlData['holds'] = db_fetch_all($sqlSelectRs);
228 
229  $sqlReturn = $sqlData;
230 
231  return $sqlReturn;
232 }
233 
234 function MemberValidateHistory($pEnv, $pContext, $pHistory) {
235  $dValidate = array();
236  foreach ($pHistory as $action => $set) {
237  if (is_array($set)) {
238  $dValidate[$action] = array();
239  foreach ($set as $key => $value) {
240  $dValidate[$action][] = array(
241  "_action" => "delete",
242  "accounttype" => prep_save($value['a_type'], 25),
243  "record" => prep_save($value['a_record'], 25)
244  );
245  }
246  }
247  }
248 
249  return $dValidate;
250 }
251 
252 function MemberDeleteHistory($pEnv, $pDbh, $pContext, $pHistory) {
253 
254  $cuTable = $pContext['cu_table'];
255  $cuMember = $pContext['m_account'];
256 
257  $cuHistoryLoan = HCU_array_key_exists('loan', $pHistory) ? $pHistory['loan'] : [];
258  $cuHistoryDeposit = HCU_array_key_exists('deposit', $pHistory) ? $pHistory['deposit'] : [];
259  $cuHistoryTransaction = HCU_array_key_exists('transactions', $pHistory) ? $pHistory['transactions'] : [];
260  $cuHistoryCrossAccounts = HCU_array_key_exists('crossaccounts', $pHistory) ? $pHistory['crossaccounts'] : [];
261  $cuHistoryMemberAcct = HCU_array_key_exists('memberacct', $pHistory) ? $pHistory['memberacct'] : [];
262  $cuHistoryHolds = HCU_array_key_exists('holds', $pHistory) ? $pHistory['holds'] : [];
263 
264  $sqlReturn = array();
265  $sqlDelete = "";
266  $sqlDeleteRs = null;
267  $sqlTrans = "";
268  $sqlTransRs = null;
269 
270  try {
271  // begin transaction
272  $sqlTrans = "BEGIN TRANSACTION";
273  $sqlTransRs = db_query($sqlTrans, $pDbh);
274 
275  // add sql for deposit deletions
276  if (count($cuHistoryDeposit) > 0) {
277  foreach ($cuHistoryDeposit as $key => $value) {
278  $sqlDelete .= "
279  DELETE FROM {$cuTable}accounthistory
280  WHERE accountnumber = '$cuMember'
281  AND accounttype = '{$value['accounttype']}';";
282 
283  $sqlDelete .= "
284  DELETE FROM {$cuTable}accountbalance
285  WHERE accountnumber = '$cuMember'
286  AND accounttype = '{$value['accounttype']}';";
287  }
288  }
289 
290  // add sql for loan deletions
291  if (count($cuHistoryLoan) > 0) {
292  foreach ($cuHistoryLoan as $key => $value) {
293  $sqlDelete .= "
294  DELETE FROM {$cuTable}loanhistory
295  WHERE accountnumber = '$cuMember'
296  AND loannumber = '{$value['accounttype']}';";
297 
298  $sqlDelete .= "
299  DELETE FROM {$cuTable}loanbalance
300  WHERE accountnumber = '$cuMember'
301  AND loannumber = '{$value['accounttype']}';";
302  }
303  }
304 
305  // add sql for transaction deletions
306  if (count($cuHistoryTransaction) > 0) {
307  foreach ($cuHistoryTransaction as $key => $value) {
308  $sqlSelect = "
309  SELECT id
310  FROM {$cuTable}transhdr
311  WHERE accountnumber = '$cuMember';";
312 
313  $sqlSelectRs = db_query($sqlSelect, $pDbh);
314  if (!$sqlSelectRs) {
315  $pEnv['logger']->error(db_last_error());
316  throw new Exception("Failed to read transaction header records.");
317  }
318 
319  $sqlData['transdtlids'] = db_fetch_all($sqlSelectRs);
320  foreach($sqlData['transdtlids'] as $hdr => $dtl) {
321  $hdrid = $dtl['id'];
322  $sqlDelete .= "
323  DELETE FROM {$cuTable}transdtl
324  WHERE transhdr_id = $hdrid;";
325 
326  }
327 
328  $sqlDelete .= "
329  DELETE FROM {$cuTable}transhdr
330  WHERE accountnumber = '$cuMember';";
331 
332  }
333  }
334 
335  // add sql for crossaccount deletions
336  if (count($cuHistoryCrossAccounts) > 0) {
337  foreach ($cuHistoryCrossAccounts as $key => $value) {
338  $sqlDelete .= "
339  DELETE FROM {$cuTable}crossaccounts
340  WHERE accountnumber = '$cuMember'
341  AND accounttype = '{$value['accounttype']}';";
342 
343  }
344  }
345 
346  // add sql for memberaccts deletions
347  if (count($cuHistoryMemberAcct) > 0) {
348  foreach ($cuHistoryMemberAcct as $key => $value) {
349  $sqlDelete .= "
350  DELETE FROM {$cuTable}memberacctrights
351  WHERE accountnumber = '$cuMember';";
352 
353  $sqlDelete .= "
354  DELETE FROM {$cuTable}memberacct
355  WHERE accountnumber = '$cuMember';";
356 
357  }
358  }
359 
360  // add sql for holds deletions
361  if (count($cuHistoryHolds) > 0) {
362  foreach ($cuHistoryHolds as $key => $value) {
363  $sqlDelete .= "
364  DELETE FROM {$cuTable}holds
365  WHERE accountnumber = '$cuMember'
366  AND accounttype = '{$value['accounttype']}';";
367 
368  }
369  }
370 
371  // delete query for all records
372  $sqlDeleteRs = db_query($sqlDelete, $pDbh);
373  if (!$sqlDeleteRs) {
374  $pEnv['logger']->error(db_last_error());
375  throw new Exception("Failed to delete account records.");
376  }
377 
378  // commit transaction
379  $sqlTrans = "COMMIT TRANSACTION";
380  $sqlTransRs = db_query($sqlTrans, $pDbh);
381 
382  } catch (Exception $e) {
383  // transaction failed
384  $pEnv['logger']->error(db_last_error());
385 
386  // revert transaction
387  $sqlTrans = "ROLLBACK TRANSACTION";
388  $sqlTransRs = db_query($sqlTrans, $pDbh);
389  throw new Exception($e->getMessage());
390  }
391 
392  // send success message
393  $sqlReturn['message'] = "Success";
394 
395  return $sqlReturn;
396 }
397 
398 ?>
399 
400 <?php function PrintMemberPurge() { ?>
401 
402  <div id="gdPurge">
403  <div class="hcu-template">
404  <div class="hcu-edit-buttons k-state-default">
405  <span class="hcu-icon-delete">
406  </span>
407  <a href="##" id="lnkCancel">Cancel</a>
408  &ensp;
409  <a href="##" id="btnUpdate" class="k-button k-primary">
410  <i class="fa fa-trash fa-lg"></i>
411  Delete
412  </a>
413  </div>
414  </div>
415  </div>
416 
417  <div id="gdInfo"></div>
418 
419  <div id="confirmationWindow"></div>
420 
421  <script type="text/x-kendo-template" id="gdOrphaned">
422  <div class="col-sm-12" id="deleteDiv">
423  <p>You are about to remove this member account and all its history records from the system.</p>
424  <p>Do you wish to continue?</p>
425  </div>
426  </script>
427 
428  <script type="text/x-kendo-template" id="gdFull">
429  <div class="col-sm-12">
430  <p>There are existing users with this account.</p>
431  <p>Member accounts cannot be deleted if there are users.
432  Use the Related Users card to view which users
433  are still using this member account.</p>
434  </div>
435  </script>
436 
437  <script id="confirmationTemplateDelete" type="text/x-kendo-template">
438  <div id="confirmationStatus"></div>
439  <div id="responseDiv">
440  <div class="local-transfer-msg">
441  #= message #
442  </div>
443  </div>
444  </script>
445 
446  <script type="text/javascript">
447 
448  var MemberPurge = function() {
449  var gdCardContainer = null;
450  var gdCardWindows = null;
451 
452  var gdCall = null;
453  var gdMember = null;
454  var gdPayload = null;
455  var gdAction = null;
456 
457  var gdDataSource = null;
458  var gdDelete = null;
459  var gdInfo = null;
460 
461  var EventOpenWindow = function(e) {
462  var windowElement = this.element[0];
463  var windowId = windowElement.id;
464 
465  switch (windowId) {
466  }
467 
468  gdCardWindows.push(this);
469  }
470 
471  var EventCloseWindow = function(e) {
472  var windowElement = this.element[0];
473  var windowId = windowElement.id;
474 
475  switch (gdAction) {
476  case "deleteConfirm":
477  EventPopWindow(windowId);
478  var memberRequest = {
479  operation: "memberPurge",
480  payload: gdPayload
481  };
482 
483  gdDataSource.transport.options.read.type = "POST";
484  gdDataSource.read(memberRequest);
485  break;
486  default:
487  EventPopWindow(windowId);
488  break;
489  }
490 
491  gdAction = null;
492 
493  }
494 
495  var EventPopWindow = function(windowId) {
496  var popIndex = -1;
497  for (var i = 0; i < gdCardWindows.length; i++) {
498  var openWindow = gdCardWindows[i].element[0];
499 
500  var openId = openWindow.id;
501 
502  if (openId == windowId) {
503  popIndex = i;
504  break;
505  }
506  }
507 
508  if (popIndex > -1) {
509  gdCardWindows.splice(popIndex, 1);
510  }
511  }
512 
513  var InitDataSources = function() {
514  gdDataSource = new kendo.data.DataSource({
515  transport: {
516  read: {
517  url: "main.prg",
518  dataType: "json",
519  contentType: "application/x-www-form-urlencoded",
520  type: "GET",
521  data: {
522  ft: "103110"
523  },
524  cache: false
525  }
526  },
527  schema: {
528  type: "json",
529  data: "response",
530  model: {
531  fields: {
532  Results: { field: "Results" }
533  }
534  }
535  },
536  requestStart: function(e) {
537  showWaitWindow();
538  },
539  requestEnd: function(e) {
540  var error = null;
541  var results = null;
542  hideWaitWindow();
543  if (e.response.hasOwnProperty("Results")) {
544  results = e.response.Results;
545  resultData = results.info;
546  ShowSuccess(resultData);
547  } else {
548  gdInfo.content("Error Parsing Server");
549  gdInfo.open();
550  return [];
551  }
552  }
553  });
554  }
555 
556  var InitDataViews = function() {
557  gdPurge = $("#gdPurge").kendoWindow({
558  title: "Delete Member",
559  modal: true,
560  visible: false,
561  resizable: false,
562  minWidth: 300,
563  maxWidth: 500,
564  activate: EventOpenWindow,
565  close: EventCloseWindow
566  }).data("kendoWindow");
567 
568  gdInfo = $("#gdInfo").kendoDialog({
569  title: "Delete Member",
570  modal: true,
571  visible: false,
572  resizable: false,
573  minWidth: 300,
574  maxWidth: 300,
575  show: EventOpenWindow,
576  close: EventCloseWindow,
577  actions: [
578  { text: "Ok", primary: true }
579  ]
580  }).data("kendoDialog");
581 
582  // Confirmation dialog
583  $("#confirmationWindow").kendoDialog({
584  title: "Success",
585  minWidth: 300,
586  maxWidth: 300,
587  modal: true,
588  visible: false,
589  resizable: false,
590  actions: [
591  {
592  text: "Close",
593  primary: true
594  }
595  ],
596  close: function() {
597  //redirect back to main account hub page
598  window.location = 'main.prg?ft=103101';
599  }
600  }).data("kendoDialog");
601 
602  }
603 
604  var InitDataActions = function() {
605  $("#btnUpdate").off();
606  $("#btnUpdate").on("click", function(e) {
607  e.preventDefault();
608  if (gdMember.m_count == 0) {
609  gdAction = "deleteConfirm";
610  gdPurge.close();
611  }
612  });
613 
614  $("#lnkCancel").off();
615  $("#lnkCancel").on("click", function(e) {
616  e.preventDefault();
617  gdAction = "deleteDeny";
618  gdPurge.close();
619  });
620  }
621 
622  var ShowSuccess = function(message) {
623  var confirmationData = { message: message };
624  var confirmationTemplate = kendo.template($("#confirmationTemplateDelete").html());
625  $("#confirmationWindow").data("kendoDialog").content(confirmationTemplate(confirmationData));
626  $("#confirmationWindow").data("kendoDialog").open().toFront().center();
627  }
628 
629  this.Open = function(windowStack) {
630  gdCardWindows = windowStack;
631 
632  if (gdMember.m_count == 0) {
633  $("#gdPurge").prepend(
634  $("#gdOrphaned").html()
635  );
636  $("#btnUpdate").show();
637  } else {
638  $("#gdPurge").prepend(
639  $("#gdFull").html()
640  );
641  $("#btnUpdate").hide();
642  }
643 
644  var template= kendo.template($("#titleTemplate").html());
645  gdMember.cardTitle= "Delete Member";
646  gdPurge.title(template(gdMember));
647  gdPurge.center();
648  gdPurge.open();
649  }
650 
651  this.Close = function() {
652  gdPurge.destroy();
653 
654  }
655 
656  this.Data = function(payload, member) {
657  gdPayload = payload;
658  gdMember = member;
659  }
660 
661  this.Init = function(hubCall, carContainer) {
662  gdCall = hubCall;
663  gdCardContainer = carContainer;
664 
665  InitDataSources();
666  InitDataViews();
667  InitDataActions();
668 
669  gdCall("MemberPurge", this);
670  }
671 
672  }
673 
674  <?php // Library javascript functions
675  getShowWaitFunctions(); ?>
676 
677  </script>
678 
679 <?php }