home *** CD-ROM | disk | FTP | other *** search
Wrap
Java Source | 1998-05-08 | 12.0 KB | 288 lines
/* * Copyright (c) 1997-1998 Borland International, Inc. All Rights Reserved. * * This SOURCE CODE FILE, which has been provided by Borland as part * of a Borland product for use ONLY by licensed users of the product, * includes CONFIDENTIAL and PROPRIETARY information of Borland. * * USE OF THIS SOFTWARE IS GOVERNED BY THE TERMS AND CONDITIONS * OF THE LICENSE STATEMENT AND LIMITED WARRANTY FURNISHED WITH * THE PRODUCT. * * IN PARTICULAR, YOU WILL INDEMNIFY AND HOLD BORLAND, ITS RELATED * COMPANIES AND ITS SUPPLIERS, HARMLESS FROM AND AGAINST ANY CLAIMS * OR LIABILITIES ARISING OUT OF THE USE, REPRODUCTION, OR DISTRIBUTION * OF YOUR PROGRAMS, INCLUDING ANY CLAIMS OR LIABILITIES ARISING OUT OF * OR RESULTING FROM THE USE, MODIFICATION, OR DISTRIBUTION OF PROGRAMS * OR FILES CREATED FROM, BASED ON, AND/OR DERIVED FROM THIS SOURCE * CODE FILE. */ //-------------------------------------------------------------------------------------------------- // CORBA Reference Application // Copyright (c) 1997 by Borland International, All Rights Reserved // // Contains logic necessary to issue credit cards. //-------------------------------------------------------------------------------------------------- package borland.reference.creditapproval.server; import borland.sql.dataset.*; import borland.jbcl.dataset.*; import borland.jbcl.control.*; import java.util.*; import borland.reference.creditapproval.CORBAInterface.*; /** * CreditHistoryReviewer reviews the credit history of a specified applicant. * * History is reviewed to determine if an applicant should be granted a cliffhanger * credit card, and if so, the amount of credit that should be extended. * * The following business rules are used: * * Credit Approval: * 1) Deny credit if 10% of all payments were late. * 2) Deny credit if any accounts are in 'COLLECTIONS'. * 3) Deny credit if the percentage of total monthly payments(TMP) * to total monthly income(TMI) is greater than 40%. * * Credit Limit calculation: * 1) Calculate maximum monthly payment (MMP): * MMP = (0.4 * TMI) - TMP * 2) Since monthly payment is 5% of total balance, the credit * limit can be calculated by dividing the MMP by 5%. * LIMIT = MMP / 0.05 * 3) Make sure credit limit is in the range of $100 - $5000 * (This range is resourced to enable conversion into foreign currency) * */ public class CreditHistoryReviewer implements DataModule{ private boolean generateRandomData; private static CreditHistoryReviewer myDM; private static final String ACCOUNT_STATUS_COLLECTIONS = "COLLECTION"; private static final String ACCOUNT_STATUS_OPEN = "OPEN"; Database acmeDb = new Database(); QueryDataSet queryCreditHistory = new QueryDataSet(); QueryDataSet queryHistoryIdLookupByName = new QueryDataSet(); QueryDataSet queryHistoryIdLookupByPid = new QueryDataSet(); ResourceBundle res = Res.getBundle("borland.reference.creditapproval.server.Res"); public CreditHistoryReviewer( boolean randomData ) throws Exception { generateRandomData = randomData; try { jbInit(); } catch (Exception e) { e.printStackTrace(); throw(e); } } private void jbInit() throws Exception{ acmeDb.setConnection(new borland.sql.dataset.ConnectionDescriptor("jdbc:odbc:ACMECreditBureau", "SYSDBA", "masterkey", false, "sun.jdbc.odbc.JdbcOdbcDriver")); acmeDb.setTransactionIsolation(java.sql.Connection.TRANSACTION_NONE); acmeDb.setSQLDialect(borland.sql.dataset.SQLDialect.INTERBASE); ParameterRow historyParameters = new ParameterRow(); historyParameters.addColumn( "HISTORYID", borland.jbcl.util.Variant.INT ); queryCreditHistory.setReadOnly(true); queryCreditHistory.setTableName(""); queryCreditHistory.setQuery(new borland.sql.dataset.QueryDescriptor(acmeDb, "SELECT TYPE, STATUS, MONTHLYPAYMENT, PASTDUE120, PASTDUE90, PASTDUE60, PASTDUE30, TOTALPAYMENTS FROM ACCOUNT WHERE HISTORYID =:HISTORYID", historyParameters, false, Load.ALL)); ParameterRow byNameParameters = new ParameterRow(); byNameParameters.addColumn( "APPLICANTDOB", borland.jbcl.util.Variant.DATE ); byNameParameters.addColumn( "APPLICANTFIRSTNAME", borland.jbcl.util.Variant.STRING ); byNameParameters.addColumn( "APPLICANTLASTNAME", borland.jbcl.util.Variant.STRING ); queryHistoryIdLookupByName.setReadOnly(true); queryHistoryIdLookupByName.setQuery(new borland.sql.dataset.QueryDescriptor(acmeDb, "SELECT HISTORYID, FIRSTNAME, MI FROM CREDITHISTORY WHERE DOB = :APPLICANTDOB AND Upper( FIRSTNAME ) = :APPLICANTFIRSTNAME AND Upper( LASTNAME ) = :APPLICANTLASTNAME", byNameParameters, false, Load.ALL)); ParameterRow byPidParameters = new ParameterRow(); byPidParameters.addColumn( "APPLICANTID", borland.jbcl.util.Variant.STRING ); queryHistoryIdLookupByPid.setDisplayErrors(true); queryHistoryIdLookupByPid.setReadOnly(true); queryHistoryIdLookupByPid.setQuery(new borland.sql.dataset.QueryDescriptor(acmeDb, "SELECT HISTORYID FROM CREDITHISTORY WHERE IDENTIFICATION = :APPLICANTID", byPidParameters, false, Load.ALL)); } /** * Connect/Disconnect to/from the database based on 'connect' parameter. */ void connect(boolean open) throws DataSetException { if (open) { // Try to connect every 5 seconds for a total of 30 seconds if (!acmeDb.isOpen()) new TimedConnect(acmeDb, 2, 8 ); } else { if (acmeDb.isOpen()) { try { acmeDb.closeConnection(); } catch (Exception e) { System.err.println( e ); } } } } /** * Return singleton instance of the DataModule */ static public CreditHistoryReviewer getDataModule() throws Exception { if (myDM == null) myDM = new CreditHistoryReviewer( false ); return myDM; } public borland.sql.dataset.QueryDataSet getQueryCreditHistory() { return queryCreditHistory; } /** * Queries the ACME Database to find a Credit History ID for the * applicant. If one does not exist, the credit history for the applicant * is not tracked by ACME and the applicant cannot be approved. */ private int getCreditHistoryId( applicantInfoStruct appInfo ) throws Exception { int historyId = -1; //return new CreditHistoryRandomData().generateRandomData( appInfo, acmeDb ); // If an IDENTIFICATION number was not specified for the applicant, // attempt to find them using their DOB and Name. if (appInfo.PID.trim().length() == 0 || appInfo.PID.trim().compareTo("0") == 0) { //ParameterRow parameters = queryHistoryIdLookupByName.getParameterRow(); ReadWriteRow parameters = queryHistoryIdLookupByName.getParameterRow(); parameters.setDate( "APPLICANTDOB", java.sql.Date.valueOf( appInfo.DOB ) ); parameters.setString( "APPLICANTFIRSTNAME", appInfo.firstName.trim().toUpperCase() ); parameters.setString( "APPLICANTLASTNAME", appInfo.lastName.trim().toUpperCase() ); queryHistoryIdLookupByName.open(); queryHistoryIdLookupByName.executeQuery(); // If the applicant is not in the ACME Database, throw an exception if (queryHistoryIdLookupByName.getRowCount() == 0) { if (generateRandomData) { return new CreditHistoryRandomData().generateRandomData( appInfo, acmeDb ); } else throw new CreditDeniedException( res.getString("Applicant_not_in_ACME")); } queryHistoryIdLookupByName.first(); historyId = queryHistoryIdLookupByName.getInt( "HISTORYID" ); } // Attempt to find the applicant using their IDENTIFICATION number else { //ParameterRow parameters = queryHistoryIdLookupByPid.getParameterRow(); ReadWriteRow parameters = queryHistoryIdLookupByPid.getParameterRow(); parameters.setString( "APPLICANTID", appInfo.PID ); queryHistoryIdLookupByPid.open(); queryHistoryIdLookupByPid.executeQuery(); // If the applicant is not in the ACME Database, throw an exception if (queryHistoryIdLookupByPid.getRowCount() == 0) { if (generateRandomData) { return new CreditHistoryRandomData().generateRandomData( appInfo, acmeDb ); } else throw new CreditDeniedException( res.getString("Applicant_not_in_ACME")); } queryHistoryIdLookupByPid.first(); historyId = queryHistoryIdLookupByPid.getInt( "HISTORYID" ); } return historyId; } /** * Implements the Credit Approval and Limit Calculation business rules. */ public creditApprovalStruct approveCredit(applicantInfoStruct appInfo) throws Exception { creditApprovalStruct approval = new creditApprovalStruct(); int historyId = getCreditHistoryId( appInfo ); // Retrieve account information for applicant. //ParameterRow parameters = queryCreditHistory.getParameterRow(); ReadWriteRow parameters = queryCreditHistory.getParameterRow(); parameters.setInt( "HISTORYID", historyId ); queryCreditHistory.open(); queryCreditHistory.executeQuery(); int rowCount = queryCreditHistory.getRowCount(); double totalMonthlyPayments = appInfo.rentMortgagePayment; double maximumMonthlyPayment = 0f; int latePaymentCount = 0; int totalPaymentsMade = 0; // Loop through all accounts and calculate then following aggregates: // 1) totalMonthlyPatments // 2) Late Payment Count // 3) Total Payments Made for (int rowLoop = 0; rowLoop < rowCount; rowLoop++) { queryCreditHistory.goToRow( rowLoop ); String status = queryCreditHistory.getString( "STATUS" ); // If any of the accounts are in COLLECTIONS, deny credit. if ( status.compareTo(ACCOUNT_STATUS_COLLECTIONS) == 0 ) { approval.approved = false; throw new CreditDeniedException(res.getString("Account_in_Collections")); } // Add the monthly payment to the total ONLY if the account // is currently open. if ( status.compareTo(ACCOUNT_STATUS_OPEN) == 0 ) { totalMonthlyPayments += queryCreditHistory.getDouble( "MONTHLYPAYMENT" ); } // Add to Payment and Late Payment counts latePaymentCount += queryCreditHistory.getShort( "PASTDUE30" ) + queryCreditHistory.getShort( "PASTDUE60" ) + queryCreditHistory.getShort( "PASTDUE90" ) + queryCreditHistory.getShort( "PASTDUE120" ); totalPaymentsMade += queryCreditHistory.getShort( "TOTALPAYMENTS" ); } // If more than 10% of all payments were late, deny credit if (totalPaymentsMade > 0) { if ((float) latePaymentCount / (float) totalPaymentsMade > 0.10f) { approval.approved = false; throw new CreditDeniedException(res.getString("Too_many_late")); } } // Determine maximum amount the applicant can afford per month. // Total Payments plus Credit Card payment cannot be more than 40% of total income. maximumMonthlyPayment = 0.40f * appInfo.monthlyIncome - totalMonthlyPayments; approval.limit = maximumMonthlyPayment / 0.05f; double minCredit = ((Double) res.getObject("Minimum_Limit")).doubleValue(); // If the limit is less than the resourced Minimum Limit, deny credit if (approval.limit < minCredit) { approval.approved = false; throw new CreditDeniedException(res.getString("You_do_not_qualify")); } // Make sure credit limit is less than the Resourced Maximum Limit double maxCredit = ((Double) res.getObject("Maximum_Limit")).doubleValue(); approval.limit = (approval.limit > maxCredit) ? maxCredit : (int) approval.limit; approval.approved = true; return approval; } public borland.sql.dataset.QueryDataSet getQueryHistoryIdLookupByName() { return queryHistoryIdLookupByName; } public borland.sql.dataset.QueryDataSet getQueryHistoryIdLookupByPid() { return queryHistoryIdLookupByPid; } }