Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loan Application Demo v2.0 code push #41

Merged
merged 2 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions LoanApplication/Python/CreditCheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import config
import time
import traceback
import datetime
import random

# Print some information messages to the user
print("\n\n***** CreditCheck *****\n")
Expand Down Expand Up @@ -53,13 +55,17 @@
# For each eent received
for loan_request_event in persistent_subscription:
# Introduce some delay
time.sleep(5)
time.sleep(config.CLIENT_PRE_WORK_DELAY)

if config.DEBUG:
print(' Received event: id=' + str(loan_request_event.id) + '; type=' + loan_request_event.type + '; stream_name=' + str(loan_request_event.stream_name) + '; data=\'' + str(loan_request_event.data) + '\'')

# Get the current commit version of the loan request stream for this loan request
COMMIT_VERSION = esdb.get_current_version(stream_name=loan_request_event.stream_name)

# Get the event data out of JSON format and into a python dictionary so we can use it
_loan_request_data = json.loads(loan_request_event.data)
_loan_request_metadata = json.loads(loan_request_event.metadata)

# Create a data structure to hold the credit score that we will return
_credit_score = -1
Expand All @@ -76,26 +82,27 @@
_credit_score = 1
# If we can't map the user name to one of the above, send for manual processing
else:
_credit_score = 5
_credit_score = random.randint(1,10)

_ts = str(datetime.datetime.now())

# Create a dictionary with the credit check data
_credit_checked_event_data = {"Score": _credit_score, "NationalID": _loan_request_data.get("NationalID")}
_credit_checked_event_data = {"Score": _credit_score, "NationalID": _loan_request_data.get("NationalID"), "CreditCheckedTimestamp": _ts}
_credit_checked_event_metadata = {"$correlationId": _loan_request_metadata.get("$correlationId"), "$causationId": str(loan_request_event.id), "transactionTimestamp": _ts}
# Create a credit checked event with the event data
credit_checked_event = NewEvent(type=config.EVENT_TYPE_CREDIT_CHECKED, data=bytes(json.dumps(_credit_checked_event_data), 'utf-8'))
credit_checked_event = NewEvent(type=config.EVENT_TYPE_CREDIT_CHECKED, metadata=bytes(json.dumps(_credit_checked_event_metadata), 'utf-8'), data=bytes(json.dumps(_credit_checked_event_data), 'utf-8'))

if config.DEBUG:
print(' Processing credit check - CreditChecked: ' + str(_credit_checked_event_data) + '\n')

print(' Processing credit check - CreditChecked for NationalID ' + str(_credit_checked_event_data["NationalID"]) + ' with a Score of ' + str(_credit_checked_event_data["Score"]))

# Get the current commit version of the loan request stream for this loan request
COMMIT_VERSION = esdb.get_current_version(stream_name=loan_request_event.stream_name)
# Append the event to the stream
CURRENT_POSITION = esdb.append_to_stream(stream_name=loan_request_event.stream_name, current_version=COMMIT_VERSION, events=[credit_checked_event])

# Acknowledge the original event
persistent_subscription.ack(loan_request_event.ack_id)

# Introduce some delay
time.sleep(5)
time.sleep(config.CLIENT_POST_WORK_DELAY)

21 changes: 15 additions & 6 deletions LoanApplication/Python/LoanDecider.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import config
import time
import traceback
import datetime

# Print some messages for the user
print("\n\n***** LoanDecider *****\n")
Expand Down Expand Up @@ -63,11 +64,17 @@
# For each event in the subscription
for credit_check_event in catchup_subscription:
# Introduce some delay
time.sleep(5)
time.sleep(config.CLIENT_PRE_WORK_DELAY)

if config.DEBUG:
print(' Received event: id=' + str(credit_check_event.id) + '; type=' + credit_check_event.type + '; stream_name=' + str(credit_check_event.stream_name) + '; data=\'' + str(credit_check_event.data) + '\'')

# Get the current commit version for the stream to which we will append
COMMIT_VERSION = esdb.get_current_version(stream_name=credit_check_event.stream_name)

# Get the metadata for the credit check event
_credit_check_metadata = json.loads(credit_check_event.metadata)

# We need to reconstruct state so that we can decide whether to automatically or manually process the loan, and push it onwards for further processing
# Read the stream for this loan request
state_stream = esdb.read_stream(credit_check_event.stream_name)
Expand Down Expand Up @@ -99,18 +106,20 @@
else:
_decision_event_type = config.EVENT_TYPE_LOAN_AUTO_DENIED

_ts = str(datetime.datetime.now())

# Create a dictionary holding the elements of the loan decision
_decision_event_data = {"LoanRequestID": _state_data.get("LoanRequestID")}
_decision_event_data = {"LoanRequestID": _state_data.get("LoanRequestID"), "LoanAutomatedDecisionTimestamp": _ts}
_decision_event_metadata = {"$correlationId": _credit_check_metadata.get("$correlationId"), "$causationId": str(credit_check_event.id), "transactionTimestamp": _ts}

# Create a decision event
decision_event = NewEvent(type=_decision_event_type, data=bytes(json.dumps(_decision_event_data), 'utf-8'))
decision_event = NewEvent(type=_decision_event_type, metadata=bytes(json.dumps(_decision_event_metadata), 'utf-8'), data=bytes(json.dumps(_decision_event_data), 'utf-8'))

if config.DEBUG:
print(' Processing loan decision - ' + _decision_event_type + ': ' + str(_decision_event_data) + '\n')

print(' Processing loan decision for ' + _state_data['User'] + ' with Score of ' + str(_state_data['Score']) + ' - ' + _decision_event_type + '\n Appending to stream: ' + credit_check_event.stream_name + '\n')

# Get the current commit version for the stream to which we will append
COMMIT_VERSION = esdb.get_current_version(stream_name=credit_check_event.stream_name)
# Append the decision event to the stream
CURRENT_POSITION = esdb.append_to_stream(stream_name=credit_check_event.stream_name, current_version=COMMIT_VERSION, events=[decision_event])

Expand All @@ -124,5 +133,5 @@
print(' Checkpoint: ' + str(credit_check_event.link.stream_position) + '\n')

# Introduce some delay
time.sleep(5)
time.sleep(config.CLIENT_POST_WORK_DELAY)

63 changes: 63 additions & 0 deletions LoanApplication/Python/LoanRequestor-commandLine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Import needed libraries
from esdbclient import EventStoreDBClient, NewEvent, StreamState
import json
import config
import time
import traceback
import uuid
import datetime

# Print some information for the user
print("\n\n***** Loan Request Command Processor *****\n")

if config.DEBUG:
print('Connecting to ESDB...')

# Create a connection to ESDB
while True:
try:
# Connect to ESDB using the URL in the config file
esdb = EventStoreDBClient(uri=config.ESDB_URL)

if config.DEBUG:
print(' Connection succeeded!')

# If the connection was successul, exit the loop
break
# If the connection fails, retry again in 10 seconds
except:
print('Connection to ESDB failed, retrying in 10 seconds...')
traceback.print_exc()
time.sleep(10)

# Loop through the samples and append events into the ESDB streams
while True:
print("Requesting a loan:")
# Get the input field data
_user = input(" What is the applicant's name? ")
_nationalid = input(" What is the applicant's national ID? ")
_amount = input(" What is the amount requested? ")
_address = input(" What is the applicant's street address? ")
_city = input(" What is the applicant's city? ")
_region = input(" What is the applicant's region? ")
_country = input(" What is the applicant's country? ")
_postal = input(" What is the applicant's postal code? ")
_loanrequestid = str(uuid.uuid4())
_ts = str(datetime.datetime.now())

# Create a dictionary for the event data, and compose the stream name to which we will append it
_loan_request_data = {"User": _user, "NationalID": _nationalid, "Amount": _amount, "LoanRequestID": _loanrequestid, "LoanRequestedTimestamp": _ts, "RequestorAddress": _address, "RequestorCity": _city, "RequestorRegion": _region, "RequestorCountry": _country, "RequestorPostalCode": _postal}
_loan_request_metadata = {"$correlationId": _loanrequestid, "$causationId": _loanrequestid, "transactionTimestamp": _ts}
_loan_request_stream_name = config.STREAM_PREFIX + '-' + _loanrequestid

# Create a loan request event
loan_request_event = NewEvent(type=config.EVENT_TYPE_LOAN_REQUESTED, metadata=bytes(json.dumps(_loan_request_metadata), 'utf-8'), data=bytes(json.dumps(_loan_request_data), 'utf-8'), id=_loanrequestid)

print('Command Received - LoanRequested: ' + str(_loan_request_data) + '\n Appending to stream: ' + _loan_request_stream_name + '\n\n')

# Append the event to the stream
CURRENT_POSITION = esdb.append_to_stream(stream_name=_loan_request_stream_name, current_version=StreamState.ANY, events=[loan_request_event])

# Wait a few seconds to let the event wind through the system
time.sleep(20)

22 changes: 16 additions & 6 deletions LoanApplication/Python/LoanRequestor-testCases.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import time
import traceback
import uuid
import datetime

# Print some information for the user
print("\n\n***** Loan Request Command Processor *****\n")
Expand All @@ -31,30 +32,39 @@

# Let's create some event data that will be appended to ESDB streams, simulating loan approval requests
_loan_request_data = []
_loan_request_metadata = []
_loan_request_stream_name = []
_loan_request_uuid = []

# Simulate an automatically approved loan
_uuid = str(uuid.uuid4())
_loan_request_data.append({"User": "Yves", "NationalID": 12345, "Amount": 10000, "LoanRequestID": _uuid})
_ts = str(datetime.datetime.now())
_loan_request_data.append({"User": "Yves", "NationalID": 12345, "Amount": 10000, "LoanRequestID": _uuid, "LoanRequestedTimestamp": _ts, "RequestorAddress": "123 Outta My Way", "RequestorCity": "Anytown", "RequestorRegion": "Wideopen", "RequestorCountry": "Fakeland", "RequestorPostalCode": "ABC 123"})
_loan_request_metadata.append({"$correlationId": _uuid, "$causationId": _uuid, "transactionTimestamp": _ts})
_loan_request_stream_name.append(config.STREAM_PREFIX + '-' + _uuid)
_loan_request_uuid.append(_uuid)

# Simulate a loan requiring manual approval / denial
_uuid = str(uuid.uuid4())
_loan_request_data.append({"User": "Tony", "NationalID": 54321, "Amount": 5000, "LoanRequestID": _uuid})
_ts = str(datetime.datetime.now())
_loan_request_data.append({"User": "Tony", "NationalID": 54321, "Amount": 5000, "LoanRequestID": _uuid, "LoanRequestedTimestamp": _ts, "RequestorAddress": "456 Some Street", "RequestorCity": "Prettyville", "RequestorRegion": "Wideopen", "RequestorCountry": "Fakeland", "RequestorPostalCode": "DEF 342"})
_loan_request_metadata.append({"$correlationId": _uuid, "$causationId": _uuid, "transactionTimestamp": _ts})
_loan_request_stream_name.append(config.STREAM_PREFIX + '-' + _uuid)
_loan_request_uuid.append(_uuid)

# Simulate another loan requiring manual approval / denial
_uuid = str(uuid.uuid4())
_loan_request_data.append({"User": "David", "NationalID": 43521, "Amount": 5000, "LoanRequestID": _uuid})
_ts = str(datetime.datetime.now())
_loan_request_data.append({"User": "David", "NationalID": 43521, "Amount": 5000, "LoanRequestID": _uuid, "LoanRequestedTimestamp": _ts, "RequestorAddress": "789 Back Lane", "RequestorCity": "Smalltown", "RequestorRegion": "Wideopen", "RequestorCountry": "Fakeland", "RequestorPostalCode": "GHJ 876"})
_loan_request_metadata.append({"$correlationId": _uuid, "$causationId": _uuid, "transactionTimestamp": _ts})
_loan_request_stream_name.append(config.STREAM_PREFIX + '-' + _uuid)
_loan_request_uuid.append(_uuid)

# Simulate a loan that is automatically denied
_uuid = str(uuid.uuid4())
_loan_request_data.append({"User": "Rob", "NationalID": 34251, "Amount": 3000, "LoanRequestID": _uuid})
_ts = str(datetime.datetime.now())
_loan_request_data.append({"User": "Rob", "NationalID": 34251, "Amount": 3000, "LoanRequestID": _uuid, "LoanRequestedTimestamp": _ts, "RequestorAddress": "742 Evergreen Terrace", "RequestorCity": "Springton", "RequestorRegion": "Wideopen", "RequestorCountry": "Fakeland", "RequestorPostalCode": "TSE 184"})
_loan_request_metadata.append({"$correlationId": _uuid, "$causationId": _uuid, "transactionTimestamp": _ts})
_loan_request_stream_name.append(config.STREAM_PREFIX + '-' + _uuid)
_loan_request_uuid.append(_uuid)

Expand All @@ -63,15 +73,15 @@
# Loop through the samples and append events into the ESDB streams
while loop_counter < len(_loan_request_data):
# Create a loan request event
loan_request_event = NewEvent(type=config.EVENT_TYPE_LOAN_REQUESTED, data=bytes(json.dumps(_loan_request_data[loop_counter]), 'utf-8'), id=_loan_request_uuid[loop_counter])
loan_request_event = NewEvent(type=config.EVENT_TYPE_LOAN_REQUESTED, metadata=bytes(json.dumps(_loan_request_metadata[loop_counter]), 'utf-8'), data=bytes(json.dumps(_loan_request_data[loop_counter]), 'utf-8'), id=_loan_request_uuid[loop_counter])

print('Command Received - LoanRequested: ' + str(_loan_request_data[loop_counter]) + '\n Appending to stream: ' + _loan_request_stream_name[loop_counter])

# Append the event to the stream
CURRENT_POSITION = esdb.append_to_stream(stream_name=_loan_request_stream_name[loop_counter], current_version=StreamState.ANY, events=[loan_request_event])

# Wait a few seconds to let the event wind through the system
time.sleep(10)
time.sleep(20)

# Increment the loop counter
loop_counter+=1
Expand Down
39 changes: 36 additions & 3 deletions LoanApplication/Python/LoanRequestor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import time
import traceback
import uuid
import datetime

# Create some variables to hold state with the GUI
esdb = None
Expand Down Expand Up @@ -45,7 +46,7 @@ def __init__(self):

# Add the panel to the window, and create a grid to hold the labels, inputs, and button
panel = wx.Panel(self)
field_grid = wx.GridSizer(rows=5, cols=2, hgap=5, vgap=5)
field_grid = wx.GridSizer(rows=10, cols=2, hgap=5, vgap=5)

# Create fields and labels for the User, NationalID, and Amount data
self.field_user = wx.TextCtrl(panel)
Expand All @@ -54,6 +55,16 @@ def __init__(self):
self.label_nationalid = wx.StaticText(panel, wx.ID_ANY, 'NationalID')
self.field_amount = wx.TextCtrl(panel)
self.label_amount = wx.StaticText(panel, wx.ID_ANY, 'Amount')
self.field_address = wx.TextCtrl(panel)
self.label_address = wx.StaticText(panel, wx.ID_ANY, 'Address')
self.field_city = wx.TextCtrl(panel)
self.label_city = wx.StaticText(panel, wx.ID_ANY, 'City')
self.field_region = wx.TextCtrl(panel)
self.label_region = wx.StaticText(panel, wx.ID_ANY, 'Region')
self.field_country = wx.TextCtrl(panel)
self.label_country = wx.StaticText(panel, wx.ID_ANY, 'Country')
self.field_postal = wx.TextCtrl(panel)
self.label_postal = wx.StaticText(panel, wx.ID_ANY, 'Postal Code')

# Create a read-only field and label for the LoanRequestID data, which we'll set to a UUID
self.field_loanrequestid = wx.TextCtrl(panel, style=wx.TE_READONLY)
Expand All @@ -66,6 +77,16 @@ def __init__(self):
field_grid.Add(self.field_nationalid, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_amount, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_amount, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_address, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_address, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_city, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_city, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_region, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_region, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_country, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_country, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_postal, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_postal, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.label_loanrequestid, 0, wx.ALL | wx.EXPAND)
field_grid.Add(self.field_loanrequestid, 0, wx.ALL | wx.EXPAND)

Expand Down Expand Up @@ -94,14 +115,21 @@ def on_press(self, event):
_user = self.field_user.GetValue()
_nationalid = self.field_nationalid.GetValue()
_amount = self.field_amount.GetValue()
_address = self.field_address.GetValue()
_city = self.field_city.GetValue()
_region = self.field_region.GetValue()
_country = self.field_country.GetValue()
_postal = self.field_postal.GetValue()
_loanrequestid = self.field_loanrequestid.GetValue()
_ts = str(datetime.datetime.now())

# Create a dictionary for the event data, and compose the stream name to which we will append it
_loan_request_data = {"User": _user, "NationalID": _nationalid, "Amount": _amount, "LoanRequestID": _loanrequestid}
_loan_request_data = {"User": _user, "NationalID": _nationalid, "Amount": _amount, "LoanRequestID": _loanrequestid, "LoanRequestedTimestamp": _ts, "RequestorAddress": _address, "RequestorCity": _city, "RequestorRegion": _region, "RequestorCountry": _country, "RequestorPostalCode": _postal}
_loan_request_metadata = {"$correlationId": _loanrequestid, "$causationId": _loanrequestid, "transactionTimestamp": _ts}
_loan_request_stream_name = config.STREAM_PREFIX + '-' + _loanrequestid

# Create a loan request event
loan_request_event = NewEvent(type=config.EVENT_TYPE_LOAN_REQUESTED, data=bytes(json.dumps(_loan_request_data), 'utf-8'), id=_loanrequestid)
loan_request_event = NewEvent(type=config.EVENT_TYPE_LOAN_REQUESTED, metadata=bytes(json.dumps(_loan_request_metadata), 'utf-8'), data=bytes(json.dumps(_loan_request_data), 'utf-8'), id=_loanrequestid)

print('Command Received - LoanRequested: ' + str(_loan_request_data) + '\n Appending to stream: ' + _loan_request_stream_name)

Expand All @@ -112,6 +140,11 @@ def on_press(self, event):
self.field_user.SetValue('')
self.field_nationalid.SetValue('')
self.field_amount.SetValue('')
self.field_address.SetValue('')
self.field_city.SetValue('')
self.field_region.SetValue('')
self.field_country.SetValue('')
self.field_postal.SetValue('')
self.field_loanrequestid.SetValue(str(uuid.uuid4()))

# Create a GUI panel to show submitted and approved / denied applications
Expand Down
Loading
Loading