implemented optional fields - needs further work

This commit is contained in:
Roland W-H 2025-02-11 18:11:54 +00:00
parent fcbc78b05b
commit 36a36f5437
3 changed files with 83 additions and 28 deletions

View File

@ -14,6 +14,7 @@ class SIPPCompare(QMainWindow):
# Initialise class variables # Initialise class variables
# Inputs # Inputs
self.optional_boxes = []
self.fund_plat_fee = 0.0 self.fund_plat_fee = 0.0
self.plat_name = "" self.plat_name = ""
self.fund_deal_fee = 0.0 self.fund_deal_fee = 0.0
@ -62,17 +63,34 @@ class SIPPCompare(QMainWindow):
# Get variables from platform editor input fields # Get variables from platform editor input fields
def init_variables(self): def init_variables(self):
self.plat_name = self.platform_win.get_plat_name() self.optional_boxes = self.platform_win.get_optional_boxes()
self.fund_plat_fee = self.platform_win.get_fund_plat_fee() self.fund_plat_fee = self.platform_win.get_fund_plat_fee()
self.fund_deal_fee = self.platform_win.get_fund_deal_fee() self.fund_deal_fee = self.platform_win.get_fund_deal_fee()
self.share_plat_fee = self.platform_win.get_share_plat_fee() self.share_plat_fee = self.platform_win.get_share_plat_fee()
self.share_plat_max_fee = self.platform_win.get_share_plat_max_fee() self.share_deal_fee = self.platform_win.get_share_deal_fee()
self.share_deal_fee = self.platform_win.get_share_deal_fee()
self.share_deal_reduce_trades = self.platform_win.get_share_deal_reduce_trades() # TODO: This is HORRIBLE - find better way of doing it! (maybe enums?)
self.share_deal_reduce_amount = self.platform_win.get_share_deal_reduce_amount() if self.optional_boxes[0]:
self.plat_name = self.platform_win.get_plat_name()
else:
self.plat_name = None
if self.optional_boxes[1]:
self.share_plat_max_fee = self.platform_win.get_share_plat_max_fee()
else:
self.share_plat_max_fee = None
if self.optional_boxes[2]:
self.share_deal_reduce_trades = self.platform_win.get_share_deal_reduce_trades()
else:
self.share_deal_reduce_trades = None
if self.optional_boxes[3]:
self.share_deal_reduce_amount = self.platform_win.get_share_deal_reduce_amount()
else:
self.share_deal_reduce_amount = None
# Calculate fees # Calculate fees
# TODO: Error checking on combo boxes
def calculate_fees(self): def calculate_fees(self):
self.init_variables() self.init_variables()
# Set to zero each time to avoid persistence # Set to zero each time to avoid persistence
@ -98,13 +116,15 @@ class SIPPCompare(QMainWindow):
break break
shares_value = (1 - (slider_val / 100)) * value_num shares_value = (1 - (slider_val / 100)) * value_num
if (self.share_plat_fee * shares_value / 12) > self.share_plat_max_fee: if self.share_plat_max_fee is not None and \
(self.share_plat_fee * shares_value / 12) > self.share_plat_max_fee:
self.share_plat_fees = self.share_plat_max_fee * 12 self.share_plat_fees = self.share_plat_max_fee * 12
else: else:
self.share_plat_fees = self.share_plat_fee * shares_value self.share_plat_fees = self.share_plat_fee * shares_value
share_trades_num = int(self.share_trades_combo.currentText()) share_trades_num = int(self.share_trades_combo.currentText())
if (share_trades_num / 12) >= self.share_deal_reduce_trades: if self.share_deal_reduce_trades is not None and \
(share_trades_num / 12) >= self.share_deal_reduce_trades:
self.share_deal_fees = self.share_deal_reduce_amount * share_trades_num self.share_deal_fees = self.share_deal_reduce_amount * share_trades_num
else: else:
self.share_deal_fees = self.share_deal_fee * share_trades_num self.share_deal_fees = self.share_deal_fee * share_trades_num

View File

@ -23,7 +23,12 @@ class OutputWindow(QWidget):
cur_time = datetime.datetime.now() cur_time = datetime.datetime.now()
if not os.path.exists("output"): if not os.path.exists("output"):
os.makedirs("output") os.makedirs("output")
filename_str = f"output/{self.platform_name}-{cur_time.year}.{cur_time.month}.{cur_time.day}.txt" filename_str = f"output/"
if self.platform_name is not None:
filename_str += f"{self.platform_name}"
else:
filename_str += "Unnamed"
filename_str += f"-{cur_time.year}.{cur_time.month}.{cur_time.day}.txt"
output_file = open(filename_str, "wt", encoding = "utf-8") output_file = open(filename_str, "wt", encoding = "utf-8")
output_file.write(self.results_str) output_file.write(self.results_str)
@ -31,7 +36,10 @@ class OutputWindow(QWidget):
def display_output(self, fund_plat_fees: float, fund_deal_fees: float, def display_output(self, fund_plat_fees: float, fund_deal_fees: float,
share_plat_fees: float, share_deal_fees: float, plat_name: str): share_plat_fees: float, share_deal_fees: float, plat_name: str):
self.platform_name = plat_name self.platform_name = plat_name
self.results_str = f"Fees breakdown (Platform \"{self.platform_name}\"):" if self.platform_name is not None:
self.results_str = f"Fees breakdown (Platform \"{self.platform_name}\"):"
else:
self.results_str = f"Fees breakdown:"
self.results_str += "\n\nPlatform fees:" self.results_str += "\n\nPlatform fees:"
# :.2f is used in order to display 2 decimal places (currency form) # :.2f is used in order to display 2 decimal places (currency form)

View File

@ -1,6 +1,6 @@
from PyQt6.QtCore import QRegularExpression, QEvent, QObject, QTimer from PyQt6.QtCore import QRegularExpression, QEvent, QObject, QTimer
from PyQt6.QtGui import QRegularExpressionValidator from PyQt6.QtGui import QRegularExpressionValidator
from PyQt6.QtWidgets import QWidget, QLayout from PyQt6.QtWidgets import QWidget
from PyQt6 import uic from PyQt6 import uic
import main_window import main_window
@ -13,6 +13,9 @@ class PlatformEdit(QWidget):
uic.loadUi("gui/platform_edit.ui", self) uic.loadUi("gui/platform_edit.ui", self)
# Initialise class variables # Initialise class variables
# Create main window object, passing this instance as param
self.main_win = main_window.SIPPCompare(self)
# TODO: Make fund_plat_fee user-defined # TODO: Make fund_plat_fee user-defined
self.fund_plat_fee = [ self.fund_plat_fee = [
[0, 250000, 1000000, 2000000], [0, 250000, 1000000, 2000000],
@ -50,35 +53,42 @@ class PlatformEdit(QWidget):
self.share_deal_reduce_amount_check self.share_deal_reduce_amount_check
] ]
# Create main window object, passing this instance as param self.check_boxes_ticked = [
self.main_win = main_window.SIPPCompare(self) True,
False,
False,
False
]
# Handle events # Handle events
# NOTE: Signal defined in UI file to close window when save button clicked
self.save_but.clicked.connect(self.init_variables)
for field in self.required_fields: for field in self.required_fields:
field.valueChanged.connect(self.check_valid) field.valueChanged.connect(self.check_valid)
field.installEventFilter(self)
for field in self.optional_fields: for field in self.optional_fields:
if field.staticMetaObject.className() == "QLineEdit": field_type = field.staticMetaObject.className()
if field_type == "QLineEdit":
field.textChanged.connect(self.check_valid) field.textChanged.connect(self.check_valid)
elif field.staticMetaObject.className() == "QDoubleSpinBox": elif field_type == "QDoubleSpinBox" or field_type == "QSpinBox":
field.valueChanged.connect(self.check_valid) field.valueChanged.connect(self.check_valid)
field.installEventFilter(self)
for check_box in self.optional_check_boxes: for check_box in self.optional_check_boxes:
check_box.checkStateChanged.connect(self.check_valid) check_box.checkStateChanged.connect(self.check_valid)
# NOTE: Signal defined in UI file to close window when save button clicked
self.save_but.clicked.connect(self.init_variables)
# Install event filter on input boxes in order to select all text on focus # Install event filter on input boxes in order to select all text on focus
# TODO: Seems like my eventFilter() override is capturing all events - need to stop this
"""
self.fund_deal_fee_box.installEventFilter(self) self.fund_deal_fee_box.installEventFilter(self)
self.share_plat_fee_box.installEventFilter(self) self.share_plat_fee_box.installEventFilter(self)
self.share_plat_max_fee_box.installEventFilter(self) self.share_plat_max_fee_box.installEventFilter(self)
self.share_deal_fee_box.installEventFilter(self) self.share_deal_fee_box.installEventFilter(self)
self.share_deal_reduce_trades_box.installEventFilter(self) self.share_deal_reduce_trades_box.installEventFilter(self)
self.share_deal_reduce_amount_box.installEventFilter(self) self.share_deal_reduce_amount_box.installEventFilter(self)
"""
#for check_box in self.optional_check_boxes:
# check_box.installEventFilter(self)
# Set validators # Set validators
# Regex accepts any characters that match [a-Z], [0-9] or _ # Regex accepts any characters that match [a-Z], [0-9] or _
@ -117,21 +127,34 @@ class PlatformEdit(QWidget):
QTimer.singleShot(0, obj.selectAll) QTimer.singleShot(0, obj.selectAll)
return False return False
# Check if all required fields have valid (non-zero) input # This method does multiple things in order to validate the user's inputs:
# 1) Check all required fields have a non-zero value
# 2) If an optional checkbox is toggled: toggle editing of the corresponding field
# 3) Check all optional fields the user has picked have a non-zero value
# 4) If the above two conditions are met (1 & 3), make the 'Save' button clickable
# 5) Keep a record of which optional fields the user has chosen to fill in
# It's called when an optional check box emits a checkStateChanged() signal
# It's also called when any field emits a textChanged() or valueChanged() signal
def check_valid(self): def check_valid(self):
valid = True valid = True
# Check all required fields have a non-zero value
for field in self.required_fields: for field in self.required_fields:
if field.value() == 0: if field.value() == 0:
valid = False valid = False
for check_box in self.optional_check_boxes: for i in range(len(self.optional_check_boxes)):
check_box_pos = self.gridLayout.getItemPosition(self.gridLayout.indexOf(check_box)) # Find the coordinates of the input box corresponding to the checkbox
# It will be on the same row, in the column to the left (-1)
check_box_idx = self.gridLayout.indexOf(self.optional_check_boxes[i])
check_box_pos = self.gridLayout.getItemPosition(check_box_idx)
input_box_pos = list(check_box_pos)[:2] input_box_pos = list(check_box_pos)[:2]
input_box_pos[1] -= 1 input_box_pos[1] -= 1
# Return copy of input field widget from its coordinates
input_box_item = self.gridLayout.itemAtPosition(input_box_pos[0], input_box_pos[1]).widget() input_box_item = self.gridLayout.itemAtPosition(input_box_pos[0], input_box_pos[1]).widget()
if check_box.isChecked(): if self.optional_check_boxes[i].isChecked():
input_box_item.setEnabled(True) input_box_item.setEnabled(True)
self.check_boxes_ticked[i] = True
input_box_type = input_box_item.staticMetaObject.className() input_box_type = input_box_item.staticMetaObject.className()
if input_box_type == "QLineEdit": if input_box_type == "QLineEdit":
if input_box_item.text() == "": if input_box_item.text() == "":
@ -141,6 +164,7 @@ class PlatformEdit(QWidget):
valid = False valid = False
else: else:
input_box_item.setEnabled(False) input_box_item.setEnabled(False)
self.check_boxes_ticked[i] = False
if valid: if valid:
self.save_but.setEnabled(True) self.save_but.setEnabled(True)
@ -148,6 +172,9 @@ class PlatformEdit(QWidget):
self.save_but.setEnabled(False) self.save_but.setEnabled(False)
# Getter functions (is this necessary? maybe directly reading class vars would be best...) # Getter functions (is this necessary? maybe directly reading class vars would be best...)
def get_optional_boxes(self):
return self.check_boxes_ticked
def get_plat_name(self): def get_plat_name(self):
return self.plat_name return self.plat_name