private function ajax_save_program() { global $FANNIE_PLUGIN_SETTINGS, $FANNIE_OP_DB; $dbc = FannieDB::get($FANNIE_PLUGIN_SETTINGS['CoopCredDatabase']); $OP = $FANNIE_OP_DB . $dbc->sep(); /* Place to accumulate not-immediately-fatal messages * that will be displayed in the ajax-return-string. */ $returnMessage = ""; /* These are from the query (parameters) string in the AJAX request * and are the same as the input form id= values. */ $progno = FormLib::get_form_value('progno', 0); $progname = FormLib::get_form_value('progname', ''); $isactive = FormLib::get_form_value('isactive', 0); $startdate = FormLib::get_form_value('startdate', ''); $enddate = FormLib::get_form_value('enddate', ''); if ($enddate == 'NULL' || $enddate == '0000-00-00') { $enddate = ''; } $tendertype = FormLib::get_form_value('tendertype', ''); $tendername = FormLib::get_form_value('tendername', ''); $tenderkeycap = FormLib::get_form_value('tenderkeycap', ''); $inputtender = FormLib::get_form_value('inputtender', ''); $paymentid = FormLib::get_form_value('paymentid', 0); $paymentname = FormLib::get_form_value('paymentname', ''); $paymentkeycap = FormLib::get_form_value('paymentkeycap', ''); $bankid = FormLib::get_form_value('bankid', 0); $creditok = FormLib::get_form_value('creditok', 0); $maxcredit = FormLib::get_form_value('maxcredit', 0); $inputok = FormLib::get_form_value('inputok', 0); $transferok = FormLib::get_form_value('transferok', 0); $origTender = FormLib::get_form_value('origtender', ''); $origDepartment = FormLib::get_form_value('origdepartment', 0); $isnew = FormLib::get_form_value('isnew', 9); /* * Check for problems, conflicts mostly: */ $sMessage = ""; /* Each check */ /* Tender */ $sErrors = array(); $sargs = array(); $sq = "SELECT tenderType, programName\n FROM CCredPrograms \n WHERE tenderType = ? "; $sargs[] = $tendertype; if (!$isnew) { $sq .= "AND programID != ?"; $sargs[] = $progno; } $ss = $dbc->prepare($sq); $sr = $dbc->execute($ss, $sargs); while ($srow = $dbc->fetch_row($sr)) { $sErrors[] = $srow['programName']; } if (count($sErrors) > 0) { $sMessage .= sprintf("\nThe Tender %s is already in use by:\n", $tendertype); $sMessage .= implode("\n", $sErrors); $sMessage .= "\nPlease choose a different one." . "\nIf the one you need doesn't exist yet,\n" . " set it up in the Tenders Editor\n" . " and then edit this Program again." . "\nAlso see the Tender '?' Help." . ""; } /* Payment Department */ $sErrors = array(); $sargs = array(); $sq = "SELECT paymentDepartment, paymentName, programName\n FROM CCredPrograms \n WHERE paymentDepartment = ? "; $sargs[] = $paymentid; if (!$isnew) { $sq .= "AND programID != ?"; $sargs[] = $progno; } $ss = $dbc->prepare($sq); $sr = $dbc->execute($ss, $sargs); while ($srow = $dbc->fetch_row($sr)) { $sErrors[] = $srow['programName']; } if (count($sErrors) > 0) { $sMessage .= sprintf("\nThe Department %s is already in use by:\n", $paymentid); $sMessage .= implode("\n", $sErrors); $sMessage .= "\nPlease choose a different one." . "\nIf the one you need doesn't exist yet,\n" . " set it up in the Departments Editor\n" . " and then edit this Program again." . "\nAlso see the Department '?' Help." . ""; } /* Banker Department */ $sErrors = array(); $sargs = array(); $sq = "SELECT bankID, programName\n FROM CCredPrograms \n WHERE bankID = ? "; $sargs[] = $bankid; if (!$isnew) { $sq .= "AND programID != ?"; $sargs[] = $progno; } $ss = $dbc->prepare($sq); $sr = $dbc->execute($ss, $sargs); while ($srow = $dbc->fetch_row($sr)) { $sErrors[] = $srow['programName']; } if (count($sErrors) > 0) { $sMessage .= sprintf("\nThe Banker %s is already in use by:\n", $bankid); $sMessage .= implode("\n", $sErrors); $sMessage .= "\nPlease choose a different one." . "\nIf the one you need doesn't exist yet,\n" . " set it up in the Members Editor\n" . " and then edit this Program again." . "\nAlso see the Banker '?' Help." . ""; } /* After all checks done. */ if ($sMessage) { $sMessage = preg_replace("/^\n+/", "", $sMessage); $sMessage .= "\n\nNo current changes have been Saved."; echo $sMessage; return; } /* Save changes to or Create the Program proper. */ $model = new CCredProgramsModel($dbc); $model->programID($progno); $model->programName($progname); /* Cannot be active if any dummy's in use. */ $resetIsactive = False; if ($isactive == 1 && ($paymentid == $this->dummyDepartment || $tendertype == "{$this->dummyTenderCode}" || $bankid == $this->dummyBanker)) { $resetIsactive = True; $isactive = 0; } $model->active($isactive); $model->startDate($startdate); $model->endDate($enddate); $model->tenderType($tendertype); $model->tenderName($tendername); $model->tenderKeyCap($tenderkeycap); $model->inputTenderType($inputtender); $model->paymentDepartment($paymentid); $model->paymentName($paymentname); $model->paymentKeyCap($paymentkeycap); $model->bankID($bankid); $model->creditOK($creditok); $model->maxCreditBalance($maxcredit); $model->inputOK($inputok); $model->transferOK($transferok); $model->modified(date('Y-m-d H:i:s')); $model->modifiedBy($this->authUserNumber); /* save() decides UPDATE vs INSERT based on whether programID already * exists. */ $saved = $model->save(); if ($isnew == 1) { if ($saved === False) { echo 'Error: could not create Program'; return; } /* Get the programID that was assigned by auto-increment. */ $newQ = "SELECT LAST_INSERT_ID()"; $rslt = $dbc->query("{$newQ}"); if ($rslt === False) { $msg = sprintf("Failed: %s", $dbc->error()); echo $msg; return; } $rows = $dbc->num_rows($rslt); if ($rows > 0) { $row = $dbc->fetch_row($rslt); $retVal = $row[0]; } else { $retVal = 0; } if ($retVal == 0) { $msg = "Failed to return new Program id."; echo $msg; return; } $progno = $retVal; $returnMessage .= sprintf("\nCreated Program %s (#%d)", $progname, $progno); /* If there are no dummies, re-create the views. */ if ($paymentid != $this->dummyDepartment && $tendertype != "{$this->dummyTenderCode}" && $bankid != $this->dummyBanker) { $rslt = $this->updateViews($dbc); if ($rslt !== True) { if (stripos($rslt, "fatal") !== False) { echo $returnMessage . "\n{$rslt}"; return; } else { $returnMessage .= "\n{$rslt}"; } } } } else { if ($saved === False) { echo 'Error: could not save the changes to the Program'; return; } else { $returnMessage .= sprintf("\nSaved Program %s (#%d)", $progname, $progno); } /* During testing pTLCC writes string error messages to Fannie log. * All problems are noted in return value. */ $laneTest = $model->pushToLanesCoopCred(); if ($laneTest === true) { $returnMessage .= "\nUpdated lanes."; } else { if (is_string($laneTest)) { $returnMessage .= sprintf("\nError saving Program %s (#%d) to lanes: %s", $progname, $progno, $laneTest); } else { $returnMessage .= sprintf("\nError saving Program %s (#%d) to lanes.", $progname, $progno); } } } /* Membership of Banker in Program * Create new membership or change Banker to this Program. * Check first that Banker has only one membership, * that something has not gone wrong. */ if ($bankid == $this->dummyBanker) { $returnMessage .= "\nThe Program may not be actually used until " . "a real Banker is assigned."; } else { $ccmModel = new CCredMembershipsModel($dbc); $ccmModel->cardNo($bankid); /* Default values for new programs. * Should these be configurable? Probably. */ $mCreditBalance = 0.0; $mCreditLimit = 0.0; $mMaxCreditBalance = 0.0; $mCreditOK = 1; $mInputOK = 1; $mTransferOK = 1; // $found = 0; $memships = array(); foreach ($ccmModel->find() as $obj) { $found++; $memships[] = $obj->programID(-1); /* Keep the values of an existing membership. * If it changes Programs. * Really a good idea? * If they, esp creditBalance, are not 0 catastrophe may ensue! */ $mCreditBalance = $obj->creditBalance(); $mCreditLimit = $obj->creditLimit(); $mMaxCreditBalance = $obj->maxCreditBalance(); $mCreditOK = $obj->creditOK(); $mInputOK = $obj->inputOK(); $mTransferOK = $obj->transferOK(); } if ($found > 1) { $msg = "Banker %d is already associated with more than one " . "(in fact %d) Program: %s" . "\nPlease use a different one."; echo $returnMessage . sprintf("\n{$msg}", $bankid, $found, implode(', ', $memships)); return; } $ccmModel = new CCredMembershipsModel($dbc); $ccmModel->cardNo($bankid); $ccmModel->programID($progno); $ccmModel->creditBalance($mCreditBalance); $ccmModel->creditLimit($mCreditLimit); $ccmModel->maxCreditBalance($mMaxCreditBalance); $ccmModel->creditOK($mCreditOK); $ccmModel->inputOK($mInputOK); $ccmModel->transferOK($mCreditOK); $ccmModel->isBank(1); $ccmModel->modified(date('Y-m-d H:i:s')); $ccmModel->modifiedBy($this->authUserNumber); $membershipSaved = $ccmModel->save(); if ($membershipSaved === False) { $msg = "Adding or updating membership in Program %d for Banker %d failed."; echo $returnMessage . sprintf("\n{$msg}", $progno, $bankid); return; } /* Membership of Banker in Program * Create new membership or change Banker to this Program. * Check first that Banker has only one membership, * that something has not gone wrong. */ $ccmModel = new CCredMembershipsModel($dbc); $ccmModel->cardNo($bankid); /* There should be one or none. * find() returns an array, possibly empty, so foreach is needed. */ /* Default values for new programs. * Should these be configurable? Probably. */ $mCreditBalance = 0.0; $mCreditLimit = 0.0; $mMaxCreditBalance = 0.0; $mCreditOK = 1; $mInputOK = 1; $mTransferOK = 1; // $found = 0; $memships = array(); foreach ($ccmModel->find() as $obj) { $found++; $memships[] = $obj->programID(-1); /* Keep the values of an existing membership. * If it changes Programs. * Really a good idea? If they are not 0 catastrophe may ensue! */ $mProgramID = $obj->programID(); $mCreditBalance = $obj->creditBalance(); $mCreditLimit = $obj->creditLimit(); $mMaxCreditBalance = $obj->maxCreditBalance(); $mCreditOK = $obj->creditOK(); $mInputOK = $obj->inputOK(); $mTransferOK = $obj->transferOK(); } if ($found > 1) { $msg = "Banker %d already has more than one (in fact %d) memberships: %s"; echo $returnMessage . sprintf("\n{$msg}", $bankid, $found, implode(', ', $memships)); return; } $ccmModel = new CCredMembershipsModel($dbc); $ccmModel->cardNo($bankid); $ccmModel->programID($progno); $ccmModel->creditBalance($mCreditBalance); $ccmModel->creditLimit($mCreditLimit); $ccmModel->maxCreditBalance($mMaxCreditBalance); $ccmModel->creditOK($mCreditOK); $ccmModel->inputOK($mInputOK); $ccmModel->transferOK($mCreditOK); $ccmModel->isBank(1); $ccmModel->modified(date('Y-m-d H:i:s')); $ccmModel->modifiedBy($this->authUserNumber); $membershipSaved = $ccmModel->save(); if ($membershipSaved === False) { $msg = "Adding or updating membership in Program %d for Banker %d failed."; $returnMessage .= sprintf("\n{$msg}", $progno, $bankid); } // not dummyBanker } /* #'u Updates to Fannie tables */ if ($tendertype == $this->dummyTenderCode) { $returnMessage .= "\nThe Program may not be actually used until " . "a real Tender is assigned."; } else { if ($tendername != "") { $opQ = "UPDATE {$OP}tenders\n SET TenderName = ?\n WHERE TenderCode = ?"; $opArgs = array(); $opArgs[] = $tendername; $opArgs[] = $tendertype; $opS = $dbc->prepare($opQ); $opR = $dbc->execute($opS, $opArgs); if ($opR === False) { $returnMessage .= "\nSaved changes to the Program proper but updating the " . "Tender name in CORE Backend failed."; } } } if ($paymentid == $this->dummyDepartment) { $returnMessage .= "\nThe Program may not be actually used until " . "a real Input/Payment is assigned."; } else { if ($paymentname != "") { $opQ = "UPDATE {$OP}departments\n SET dept_name = ?\n WHERE dept_no = ?"; $opArgs = array(); $opArgs[] = $paymentname; $opArgs[] = $paymentid; $opS = $dbc->prepare($opQ); $opR = $dbc->execute($opS, $opArgs); if ($opR === False) { $returnMessage .= "\nSaved changes to the Program proper but updating the " . "Department name in CORE Backend failed."; } } } /* Update views if Department or Tender have changed and * as long as neither is dummy. */ if ($paymentid != $origDepartment || $tendertype != $origTender) { if ($paymentid != $this->dummyDepartment && $tendertype != "{$this->dummyTenderCode}" && $bankid != $this->dummyBanker) { $rslt = $this->updateViews($dbc); if ($rslt !== True) { if (stripos($rslt, "fatal") !== False) { echo $returnMessage . "\n{$rslt}"; return; } else { $returnMessage .= "\n{$rslt}"; } } else { $returnMessage .= "\nUpdated views."; } } } if ($resetIsactive) { $returnMessage .= "\nThe Program has been marked Not-Active because " . "one or more dummy values are in use."; } $returnMessage = preg_replace("/^\n+/", "", $returnMessage); echo $returnMessage; // ajax_save_program() }
/** OK to use the tender or make the input? @return True if all clear to charge or input to the program message if not @param $pKey - a tenderType or paymentDepartment Note: Transfer-to-another member part is not done. * * Knowing tenderType or paymentDepartment and memberID * Step 1: * - Find the program * Step 2: * - Is the program active? * Step 3: * - Is the member in it? CCredMemberships record exists. * - Is the membership in the program active? * x Is there enough to cover the amount? */ public static function programOK($pKey = '', $conn = '') { global $CORE_LOCAL; if (!$CORE_LOCAL->get("memberID")) { return _("Please enter the Member ID"); } if ($conn == '') { $conn = self::ccDataConnect(); if (!is_object($conn)) { return _("Coop Cred database connection failed:") . " {$conn}"; } } $pKeyType = preg_match('/^\\d+$/', $pKey) ? 'Department' : 'Tender'; $ccpModel = new CCredProgramsModel($conn); if ($pKeyType == 'Department') { $ccpModel->paymentDepartment($pKey); } else { $ccpModel->tenderType($pKey); } $pCount = 0; foreach ($ccpModel->find() as $pgm) { $pCount++; //$limit = $cdModel->ChargeLimit(); //$prog['inputOK'] = $pgm->inputOK(); } if ($pCount == 0) { return _("Error:") . " {$pKeyType}" . " '{$pKey}' " . _("is not used in any Coop Cred Program."); } if ($pCount > 1) { return _("Error:") . " {$pKeyType}" . " '{$pKey}' " . _("is used in more than one Coop Cred Program."); } $today = date('Y-m-d'); if ($today < $pgm->startDate()) { return $pgm->programName() . _(" hasn't started yet."); } if ($today < $pgm->endDate() != '' && $today > $pgm->endDate()) { return $pgm->programName() . _(" is no longer operating."); } if (!$pgm->active()) { return $pgm->programName() . _(" is not active."); } if (!$pgm->creditOK()) { return $pgm->programName() . _(" is not accepting purchases at this time."); } /* These are only valid globally for calculations involving the * current tenderType or paymentDepartment. */ $CORE_LOCAL->set("CCredProgramID", $pgm->programID()); $programCode = "CCred{$pgm->programID()}"; $CORE_LOCAL->set("CCredProgramCode", $programCode); /* Reset these in CoopCred::plugin_transaction_reset() */ $CORE_LOCAL->set("{$programCode}programID", $pgm->programID()); $CORE_LOCAL->set("{$programCode}programName", $pgm->programName()); $CORE_LOCAL->set("{$programCode}paymentDepartment", $pgm->paymentDepartment()); $CORE_LOCAL->set("{$programCode}paymentName", $pgm->paymentName()); $CORE_LOCAL->set("{$programCode}paymentKeyCap", $pgm->paymentKeyCap()); $CORE_LOCAL->set("{$programCode}tenderType", $pgm->tenderType()); $CORE_LOCAL->set("{$programCode}tenderName", $pgm->tenderName()); $CORE_LOCAL->set("{$programCode}tenderKeyCap", $pgm->tenderKeyCap()); /* Membership info. * (At the moment members's name is not used, so a model query could be used.) */ $query = "SELECT m.creditBalance, m.creditLimit, m.creditOK, m.inputOK,\n m.transferOK, m.isBank\n ,(m.creditLimit - m.creditBalance) as availCreditBalance\n ,c.FirstName, c.LastName\n FROM CCredMemberships m\n JOIN {$CORE_LOCAL->get('pDatabase')}.custdata c\n ON m.cardNo = c.CardNo\n WHERE m.cardNo = ? AND m.programID = ? AND c.personNum=1"; $statement = $conn->prepare_statement($query); if ($statement === False) { return "Error: prepare_statement() failed for query: {$query}"; } $args = array((int) $CORE_LOCAL->get("memberID"), (int) $pgm->programID()); $result = $conn->exec_statement($statement, $args); if ($result === False) { return "Error: exec_statement() failed for query: {$query} args:" . implode('|', $args); } $num_rows = $conn->num_rows($result); if ($num_rows == 0) { return _("Member ") . $CORE_LOCAL->get("memberID") . _(" is not registered for ") . $CORE_LOCAL->get("{$programCode}programName") . "."; } $mem = $conn->fetch_array($result); /* Suspended or not activated for either purchasing or input. */ if (!$mem['creditOK']) { return _("Member #") . $CORE_LOCAL->get("memberID") . _(" is registered for ") . '<b>' . $CORE_LOCAL->get("{$programCode}programName") . '</b>' . _(" but may not use it") . _(" at this time") . "."; } /* May not put money into the program. */ if ($pKeyType == "Department" && !$mem['inputOK']) { return _("Member #") . $CORE_LOCAL->get("memberID") . _(" may not pay into ") . $CORE_LOCAL->get("{$programCode}programName") . "."; } /* May not transfer to another member. * I can't think how this could be done at cash without a special popup. * Transfer among one's own accounts: input to one, tender from another. * Test would be at point of tender and need a scan of localtemptrans * for CoopCredDepartments, $CoopCredDepartmentsUsed. * "Payments" better, "Inputs" even better. * AND trans_status in ('','0') - not cancel, void, refund - what would that be? */ $isTransfer = 0; if (!$mem['transferOK'] && $isTransfer) { return _("Member #") . $CORE_LOCAL->get("memberID") . _(" may not transfer Coop Cred to another Member") . "."; } $CORE_LOCAL->set("{$programCode}availCreditBalance", $mem['availCreditBalance']); $CORE_LOCAL->set("{$programCode}creditBalance", $mem['creditBalance']); return True; // programOK() }