mirror of
https://github.com/RolandWH/SIPPCompare.git
synced 2025-03-14 22:01:36 +00:00
platform edit error checking, more comments, misc other changes
This commit is contained in:
parent
6b4f6bb35f
commit
1748fb849f
@ -58,25 +58,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="value_input">
|
||||
<property name="inputMask">
|
||||
<string>£0000000000</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>£</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="cursorPosition">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="mix_lab">
|
||||
<property name="text">
|
||||
@ -138,6 +119,28 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="value_input">
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>£</string>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>£</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.990000009536743</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>484</width>
|
||||
<height>290</height>
|
||||
<width>481</width>
|
||||
<height>305</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -19,7 +19,7 @@
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>461</width>
|
||||
<height>226</height>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
@ -36,32 +36,11 @@
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_plat_max_fee_lab">
|
||||
<property name="text">
|
||||
<string>Share platform fee cap (£/mth)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_deal_reduce_amount_lab">
|
||||
<property name="text">
|
||||
<string>Share dealing fee discount (£)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_deal_fee_lab">
|
||||
<property name="text">
|
||||
<string>Share dealing fee (£)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<property name="verticalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="plat_name_lab">
|
||||
<property name="text">
|
||||
@ -69,14 +48,12 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLineEdit" name="share_deal_fee_box"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="fund_deal_fee_box"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="share_plat_fee_box"/>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_deal_reduce_amount_lab">
|
||||
<property name="text">
|
||||
<string>Share dealing discount amount</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="plat_name_box"/>
|
||||
@ -84,26 +61,10 @@
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_plat_fee_lab">
|
||||
<property name="text">
|
||||
<string>Share platform fee (%)</string>
|
||||
<string>Share platform fee*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="share_plat_max_fee_box"/>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLineEdit" name="share_deal_reduce_trades_box"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="fund_deal_fee_lab">
|
||||
<property name="text">
|
||||
<string>Fund dealing fee (£)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLineEdit" name="share_deal_reduce_amount_box"/>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_deal_reduce_trades_lab">
|
||||
<property name="text">
|
||||
@ -111,14 +72,113 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_deal_fee_lab">
|
||||
<property name="text">
|
||||
<string>Share dealing fee*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="fund_deal_fee_lab">
|
||||
<property name="text">
|
||||
<string>Fund dealing fee*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="share_plat_max_fee_lab">
|
||||
<property name="text">
|
||||
<string>Share platform fee cap/mth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QDoubleSpinBox" name="share_deal_reduce_amount_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>£</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QDoubleSpinBox" name="share_deal_fee_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>£</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QDoubleSpinBox" name="share_plat_max_fee_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>£</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QDoubleSpinBox" name="share_plat_fee_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDoubleSpinBox" name="fund_deal_fee_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>£</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QSpinBox" name="share_deal_reduce_trades_box">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="save_but">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>290</x>
|
||||
<y>260</y>
|
||||
<width>191</width>
|
||||
<x>330</x>
|
||||
<y>270</y>
|
||||
<width>141</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -126,6 +186,19 @@
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>270</y>
|
||||
<width>191</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>* Indicates required field</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>plat_name_box</tabstop>
|
||||
@ -133,7 +206,6 @@
|
||||
<tabstop>share_plat_fee_box</tabstop>
|
||||
<tabstop>share_plat_max_fee_box</tabstop>
|
||||
<tabstop>share_deal_fee_box</tabstop>
|
||||
<tabstop>share_deal_reduce_trades_box</tabstop>
|
||||
<tabstop>share_deal_reduce_amount_box</tabstop>
|
||||
<tabstop>save_but</tabstop>
|
||||
</tabstops>
|
||||
|
10
src/main.py
10
src/main.py
@ -7,6 +7,14 @@ import platform_edit
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
# Show platform edit window first, before main win
|
||||
window = platform_edit.PlatformEdit()
|
||||
# When debugging, can be useful to autofill values to save time
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] == "--DEBUG_AUTOFILL":
|
||||
window = platform_edit.PlatformEdit(True)
|
||||
else:
|
||||
window = platform_edit.PlatformEdit(False)
|
||||
else:
|
||||
window = platform_edit.PlatformEdit(False)
|
||||
|
||||
window.show()
|
||||
app.exec()
|
||||
|
@ -1,3 +1,4 @@
|
||||
from PyQt6.QtGui import QIntValidator
|
||||
from PyQt6.QtWidgets import QMainWindow
|
||||
from PyQt6 import uic
|
||||
|
||||
@ -8,9 +9,11 @@ class SIPPCompare(QMainWindow):
|
||||
# Receive instance of PlatformEdit() as parameter
|
||||
def __init__(self, plat_edit_win):
|
||||
super().__init__()
|
||||
# Import Qt Designer UI XML file
|
||||
uic.loadUi("gui/main_gui.ui", self)
|
||||
|
||||
# Initialise class variables
|
||||
# Inputs
|
||||
self.fund_plat_fee = 0.0
|
||||
self.plat_name = ""
|
||||
self.fund_deal_fee = 0.0
|
||||
@ -20,6 +23,7 @@ class SIPPCompare(QMainWindow):
|
||||
self.share_deal_reduce_trades = 0.0
|
||||
self.share_deal_reduce_amount = 0.0
|
||||
|
||||
# Results
|
||||
self.fund_plat_fees = 0.0
|
||||
self.fund_deal_fees = 0.0
|
||||
self.share_plat_fees = 0.0
|
||||
@ -31,16 +35,22 @@ class SIPPCompare(QMainWindow):
|
||||
|
||||
# Handle events
|
||||
self.calc_but.clicked.connect(self.calculate_fees)
|
||||
# Menu bar entry (File -> Edit Platforms)
|
||||
self.actionEdit_Platforms.triggered.connect(self.show_platform_edit)
|
||||
# Update percentage mix label when slider moved
|
||||
self.mix_slider.valueChanged.connect(self.update_slider_lab)
|
||||
|
||||
# Set validators
|
||||
self.share_trades_combo.setValidator(QIntValidator(0, 999))
|
||||
self.fund_trades_combo.setValidator(QIntValidator(0, 99))
|
||||
|
||||
# Display slider position as mix between two nums (funds/shares)
|
||||
def update_slider_lab(self):
|
||||
slider_val = self.mix_slider.value()
|
||||
mix_lab_str = f"Investment mix (funds {slider_val}% / shares {100 - slider_val}%)"
|
||||
self.mix_lab.setText(mix_lab_str)
|
||||
|
||||
# Get local variables from user input
|
||||
# Get variables from platform editor input fields
|
||||
def init_variables(self):
|
||||
self.plat_name = self.platform_win.get_plat_name()
|
||||
self.fund_plat_fee = self.platform_win.get_fund_plat_fee()
|
||||
@ -52,15 +62,17 @@ class SIPPCompare(QMainWindow):
|
||||
self.share_deal_reduce_amount = self.platform_win.get_share_deal_reduce_amount()
|
||||
|
||||
# Calculate fees
|
||||
# TODO: Error checking on combo boxes
|
||||
def calculate_fees(self):
|
||||
self.init_variables()
|
||||
# Set to zero each time to avoid persistence
|
||||
self.fund_plat_fees = 0
|
||||
value_num = float(self.value_input.text()[1:]) # Filter out '£' symbol
|
||||
value_num = float(self.value_input.value())
|
||||
# Funds/shares mix
|
||||
slider_val = self.mix_slider.value()
|
||||
funds_value = (slider_val / 100) * value_num
|
||||
fund_trades_num = int(self.fund_trades_combo.currentText())
|
||||
self.fund_deal_fees = fund_trades_num * self.fund_deal_fee
|
||||
remaining = funds_value
|
||||
|
||||
for i in range(1, len(self.fund_plat_fee[0])):
|
||||
band = self.fund_plat_fee[0][i]
|
||||
@ -68,11 +80,11 @@ class SIPPCompare(QMainWindow):
|
||||
fee = self.fund_plat_fee[1][i]
|
||||
gap = (band - prev_band)
|
||||
|
||||
if remaining > gap:
|
||||
if funds_value > gap:
|
||||
self.fund_plat_fees += gap * (fee / 100)
|
||||
remaining -= gap
|
||||
funds_value -= gap
|
||||
else:
|
||||
self.fund_plat_fees += remaining * (fee / 100)
|
||||
self.fund_plat_fees += funds_value * (fee / 100)
|
||||
break
|
||||
|
||||
shares_value = (1 - (slider_val / 100)) * value_num
|
||||
@ -93,7 +105,9 @@ class SIPPCompare(QMainWindow):
|
||||
def show_output_win(self):
|
||||
# Refresh the results when new fees are calculated
|
||||
self.output_win.display_output(self.fund_plat_fees, self.fund_deal_fees,
|
||||
self.share_plat_fees, self.share_deal_fees, self.plat_name)
|
||||
self.share_plat_fees, self.share_deal_fees,
|
||||
self.plat_name
|
||||
)
|
||||
self.output_win.show()
|
||||
|
||||
# Show the platform editor window (currently run-time only)
|
||||
|
@ -8,6 +8,7 @@ import os
|
||||
class OutputWindow(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# Import Qt Designer UI XML file
|
||||
uic.loadUi("gui/output_window.ui", self)
|
||||
|
||||
# Initialise class variables
|
||||
|
@ -1,3 +1,5 @@
|
||||
from PyQt6.QtCore import QRegularExpression, QEvent, QObject, QTimer
|
||||
from PyQt6.QtGui import QRegularExpressionValidator
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
from PyQt6 import uic
|
||||
|
||||
@ -5,8 +7,9 @@ import main_window
|
||||
|
||||
|
||||
class PlatformEdit(QWidget):
|
||||
def __init__(self):
|
||||
def __init__(self, autofill: bool):
|
||||
super().__init__()
|
||||
# Import Qt Designer UI XML file
|
||||
uic.loadUi("gui/platform_edit.ui", self)
|
||||
|
||||
# Initialise class variables
|
||||
@ -22,28 +25,83 @@ class PlatformEdit(QWidget):
|
||||
self.share_deal_fee = 0.0
|
||||
self.share_deal_reduce_trades = 0.0
|
||||
self.share_deal_reduce_amount = 0.0
|
||||
# Debugging feature: set with "--DEBUG_AUTOFILL" cmd argument
|
||||
self.autofill = autofill
|
||||
|
||||
# Create main window object, passing this instance as param
|
||||
self.main_win = main_window.SIPPCompare(self)
|
||||
|
||||
# Handle events
|
||||
# NOTE: Signal defined in Qt designer to close window when clicked
|
||||
# NOTE: Signal defined in UI file to close window when save button clicked
|
||||
self.save_but.clicked.connect(self.init_variables)
|
||||
self.fund_deal_fee_box.valueChanged.connect(self.check_valid)
|
||||
self.share_plat_fee_box.valueChanged.connect(self.check_valid)
|
||||
self.share_deal_fee_box.valueChanged.connect(self.check_valid)
|
||||
|
||||
# Get fee structure variables from user input
|
||||
# Install event filter on input boxes in order to select all text on focus
|
||||
self.fund_deal_fee_box.installEventFilter(self)
|
||||
self.share_plat_fee_box.installEventFilter(self)
|
||||
self.share_plat_max_fee_box.installEventFilter(self)
|
||||
self.share_deal_fee_box.installEventFilter(self)
|
||||
self.share_deal_reduce_trades_box.installEventFilter(self)
|
||||
self.share_deal_reduce_amount_box.installEventFilter(self)
|
||||
|
||||
# Set validators
|
||||
# Regex accepts any characters that match [a-Z], [0-9] or _
|
||||
self.plat_name_box.setValidator(
|
||||
QRegularExpressionValidator(QRegularExpression("\\w*"))
|
||||
)
|
||||
|
||||
# Get fee structure variables from user input when "Save" clicked
|
||||
def init_variables(self):
|
||||
self.plat_name = self.plat_name_box.text()
|
||||
self.fund_deal_fee = float(self.fund_deal_fee_box.text())
|
||||
self.share_plat_fee = float(self.share_plat_fee_box.text()) / 100
|
||||
self.share_plat_max_fee = float(self.share_plat_max_fee_box.text())
|
||||
self.share_deal_fee = float(self.share_deal_fee_box.text())
|
||||
self.share_deal_reduce_trades = float(self.share_deal_reduce_trades_box.text())
|
||||
self.share_deal_reduce_amount = float(self.share_deal_reduce_amount_box.text())
|
||||
# If debugging, save time by hardcoding
|
||||
if self.autofill:
|
||||
self.plat_name = "AJBell"
|
||||
self.fund_deal_fee = 1.50
|
||||
self.share_plat_fee = 0.0025
|
||||
self.share_plat_max_fee = 3.50
|
||||
self.share_deal_fee = 5.00
|
||||
self.share_deal_reduce_trades = 10
|
||||
self.share_deal_reduce_amount = 3.50
|
||||
else:
|
||||
self.plat_name = self.plat_name_box.text()
|
||||
self.fund_deal_fee = float(self.fund_deal_fee_box.value())
|
||||
self.share_plat_fee = float(self.share_plat_fee_box.value()) / 100
|
||||
self.share_plat_max_fee = float(self.share_plat_max_fee_box.value())
|
||||
self.share_deal_fee = float(self.share_deal_fee_box.value())
|
||||
self.share_deal_reduce_trades = float(self.share_deal_reduce_trades_box.value())
|
||||
self.share_deal_reduce_amount = float(self.share_deal_reduce_amount_box.value())
|
||||
|
||||
# Once user input is received show main window
|
||||
self.main_win.show()
|
||||
|
||||
# Getter functions
|
||||
# When focus is given to an input box, select all text in it (easier to edit)
|
||||
def eventFilter(self, obj: QObject, event: QEvent):
|
||||
if event.type() == QEvent.Type.FocusIn:
|
||||
# Alternative condition for % suffix - currently unused
|
||||
#if obj.value() == 0 or obj == self.share_plat_fee_box:
|
||||
QTimer.singleShot(0, obj.selectAll)
|
||||
return False
|
||||
|
||||
# Check if all required fields have valid (non-zero) input
|
||||
# TODO: Find a better way of doing this if possible
|
||||
def check_valid(self):
|
||||
values = [self.fund_deal_fee_box.value(),
|
||||
self.share_plat_fee_box.value(),
|
||||
self.share_deal_fee_box.value()
|
||||
]
|
||||
valid = True
|
||||
|
||||
for value in values:
|
||||
if value == 0:
|
||||
valid = False
|
||||
|
||||
if valid:
|
||||
self.save_but.setEnabled(True)
|
||||
else:
|
||||
self.save_but.setEnabled(False)
|
||||
|
||||
# Getter functions (is this necessary? maybe directly reading class vars would be best...)
|
||||
def get_plat_name(self):
|
||||
return self.plat_name
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user