Coding more features

So far, we have coded a few of our requirements from front to back. We built the view layer using CherryPy. Next, we configured security to protect the site. Then we fully implemented one of the customer features so that it stored new accounts in the database.

Coding more features follows a similar pattern. The order the steps are executed are a matter of taste. It is possible to code the entire back end using automated testing, followed by skinning it with a web layer. In our case, we used the more demonstrative style of building the interface first, and then fleshing out the backend later. Either way, it is easy to iterate through and see how Spring Python's IoC container kept the security, view, and controller logic nicely decoupled.

Now let's fast forward development to the point where all the customer features are implemented.

Updating the main page with more features

We updated the index page in SpringBankView, so that it lists the customer's current accounts as well as listing the other functions available.

Updating the main page with more features

In this example, Alice already has two accounts created. In the previous version, they weren't listed, but now they are.

@cherrypy.expose
def index(self, message=""):
results = """
<h1>Welcome to SpringBank!</h1>
<p>
%s
<p>
""" % message
if "ROLE_CUSTOMER" in 
SCH.getContext().authentication.granted_auths:
results += """
<h2>Existing Accounts</h2>
<table border="1">
<tr><th>Account</th><th>Description </th><th>Balance</th></tr>
"""
for account in self.controller.get_accounts( SCH.getContext().authentication.username):
results += '''
<tr>
<td>%s</td><td><a href="history?id=%s">%s</a> </td><td>%s</td>
</tr>
''' % (account["id"], account["id"], account["description"], account["balance"])
results += """
</table>
<h2>Customer Options</h2>
<ul>
<li><a href="openAccount">Open Account</a></li>
<li><a href="closeAccount">Close Account</a></li>
<li><a href="withdraw">Withdraw Money</a></li>
<li><a href="deposit">Deposit Money</a></li>
<li><a href="transfer">Transfer</a></li>
</ul>
"""
results += """
<a href="logout">Logout</a href>
"""
return results

As you can see, wedged into the middle is a for-loop that generates rows in an HTML table, listing the accounts the user owns. get_accounts is delegated to the controller.

def get_accounts(self, username):
return self.dt.query("""
SELECT id, description, balance
FROM account
WHERE owner = ?
AND status = 'OPEN'""", (username,),
DictionaryRowMapper())

Each row includes a link to view the history for that account, and at the bottom of the screen are links to the other new functions.

Refining the ability to open an account

We altered the back end of openAccount by marking new accounts with a state of OPEN.

def open_account(self, description):
self.dt.execute("""
INSERT INTO account
(description, balance, owner, status)
VALUES
(?, 0.0, ?, 'OPEN')""", (description,
SCH.getContext().authentication.username))
self.log("TX", self.get_latest_account(), "Opened account %s" % description)

We also added the extra step of writing a transaction log entry. To support writing the log entry, the controller must retrieve the latest account created for this customer.

def get_latest_account(self):
return self.dt.query_for_long("""
SELECT max(id)
FROM account
WHERE owner = ?
AND status = 'OPEN'""", 
(SCH.getContext().authentication.username,))

open_account, along with several of the other controller operations uses the following code to write log entries.

def log(self, type, account, message):
self.dt.execute("""
INSERT INTO log
(type, account, message)
values
(?, ?, ?)""", 
(type, account, message))

Adding the ability to close an account

We added closeAccount to SpringBankView to let the customer close an existing account if its balance is zero.

Adding the ability to close an account
@cherrypy.expose
def closeAccount(self, id=""):
if id != "":
self.controller.close_account(id)
raise cherrypy.HTTPRedirect("/?message= Account successfully closed")
results = """
<h2>Close an Account</h2>
<form method="POST" action="">
<table border="1">
<tr><th>Account</th></tr>
"""
for account in self.controller.closeable_accounts( SCH.getContext().authentication.username):
customer features, banking applicationcloseAccount operation, addingresults += """
<tr><td><a href="closeAccount?id=%s">%s - %s</a> </td></tr>
""" % (account["id"], account["id"], account["description"])
results += """
</table>
</form>
<a href="/">Cancel</a>
"""
return results

Looking up closeable_accounts as well as completing the close_account operation is delegated to the controller.

def closeable_accounts(self, username):
return self.dt.query("""
SELECT id, description
FROM account
WHERE owner = ?
AND balance = 0.0
AND status = 'OPEN'""", (username,),
DictionaryRowMapper())
def close_account(self, id):
self.dt.execute("""
UPDATE account
SET status = 'CLOSED'
WHERE id = ?""", (id,))
self.log("TX", id, "Closed account")

Opening a new account causes a row to be inserted into the ACCOUNT table. However, closing an account does not mean deleting the same row. Instead, its status is updated to CLOSED.

Adding the ability to withdraw money

We added withdraw to SpringBankView to let the customer withdraw money from an existing account.

Adding the ability to withdraw money
@cherrypy.expose
def withdraw(self, id="", amount=""):
if id != "" and amount != "":
self.controller.withdraw(id, float(amount))
raise cherrypy.HTTPRedirect("/?message=Successfully withdrew %s" % amount)
results = """
<h2>Withdraw Money</h2>
<form method="POST" action="">
<table border="1">
<tr>
<td>Amount</td>
<td><input type="text" name="amount"/></td>
</tr>
<tr><td colspan="2">
"""
for account in self.controller.get_accounts(SCH.getContext().authentication.username):
customer features, banking applicationwithdraw operation, addingresults += """
<input type="radio" name="id" value="%s">%s - %s</input><br/>
""" % (account["id"], account["id"], account["description"])
results += """
</td></tr>
<tr><td colspan="2"><input type="submit"/></td></tr>
</form>
"""
return results

When the user clicks submit, withdraw is delegated to the controller.

def withdraw(self, id, amount):
self.dt.execute("""
UPDATE account
SET balance = balance - ?
WHERE id = ?""", (amount, id))
self.log("TX", id, "Withdrew %s" % amount)

Adding the ability to deposit money

We added deposit to SpringBankView to let the customer deposit money into an existing account.

Adding the ability to deposit money
@cherrypy.expose
def deposit(self, id="", amount=""):
if id != "" and amount != "":
self.controller.deposit(id, float(amount))
raise cherrypy.HTTPRedirect("/?message=Successfully deposited %s" % amount)
results = """
<h2>Deposit Money</h2>
<form method="POST" action="">
<table border="1">
<tr>
<td>Amount</td>
<td><input type="text" name="amount"/></td>
</tr>
<tr><td colspan="2">
"""
for account in self.controller.get_accounts(SCH.getContext().authentication.username):
results += """
<input type="radio" name="id" value="%s">%s - %s</input><br/>
""" % (account["id"], account["id"], account["description"])
results += """
</td></tr>
<tr><td colspan="2"><input type="submit"/></td></tr>
</form>
"""
return results

When the user clicks submit, deposit is delegated to the controller.

def deposit(self, id, amount):
self.dt.execute("""
UPDATE account
SET balance = balance + ?
WHERE id = ?""", (amount, id))
self.log("TX", id, "Deposited %s" % amount)

Adding the ability to transfer money

We added transfer to SpringBankView to let the customer transfer money from one account to the other.

Adding the ability to transfer money
@cherrypy.expose
def transfer(self, amount="", source="", target=""):
if amount != "" and source != "" and target != "":
self.controller.transfer(amount, source, target)
raise cherrypy.HTTPRedirect("/?message=Successful transfer")
results = """
customer features, banking applicationtransfer operation, adding<h2>Transfer Money</h2>
<form method="POST" action="">
<table border="1">
<tr>
<td>Amount</td>
<td><input type="text" name="amount"/></td>
</tr>
"""
accounts = self.controller.get_accounts(SCH.getContext().authentication.username)
for param in ["source", "target"]:
results += '<tr><td>%s</td><td>' % (param[0].upper() + param[1:])
for account in accounts:
results += """
<input type="radio" name="%s" value="%s">%s - %s</input><br/>
""" % (param, account["id"], account["id"], account["description"])
results += "</td></tr>"
results += """
<tr><td colspan="2"><input type="submit"/></td></tr>
</form>
"""
return results

When the user clicks submit, transfer is delegated to the controller.

def transfer(self, amount, source, target):
self.withdraw(source, amount)
self.deposit(target, amount)

transfer conveniently re-uses withdraw and deposit.

Showing account history

The last customer facing feature added was the ability to view an account's history.

Showing account history
@cherrypy.expose
def history(self, id):
results = """
<table border="1">
"""
for entry in self.controller.history(id):
results += """
<tr><td>%s</td><td>%s</td></tr>
""" % (entry["date"], entry["message"])
results += """
<table>
"""
return results

When the user clicks submit, history is delegated to the controller.

def history(self, id):
return self.dt.query("""
SELECT type, date, message
FROM log
WHERE log.account = ?
AND log.type = 'TX'""", (id,),
DictionaryRowMapper())
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.223.10