Merge branch 'main' of g.8f.al:ir/budget
This commit is contained in:
commit
b252d1ee2c
5 changed files with 169 additions and 10 deletions
|
@ -28,9 +28,9 @@ class CategoryTab(TabPage):
|
||||||
topLayout.addWidget(self.categoryAddButton)
|
topLayout.addWidget(self.categoryAddButton)
|
||||||
|
|
||||||
# 创建表格
|
# 创建表格
|
||||||
self.accountTable = QTableWidget()
|
self.categoryTable = QTableWidget()
|
||||||
tableLayout = QVBoxLayout()
|
tableLayout = QVBoxLayout()
|
||||||
tableLayout.addWidget(self.accountTable)
|
tableLayout.addWidget(self.categoryTable)
|
||||||
|
|
||||||
# 应用布局
|
# 应用布局
|
||||||
categoryLayout = QVBoxLayout()
|
categoryLayout = QVBoxLayout()
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
from PyQt6.QtWidgets import *
|
|
||||||
from PyQt6.QtCore import *
|
|
|
@ -9,7 +9,7 @@ from ._stat import StatTab
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
|
|
||||||
self.setWindowTitle('budget')
|
self.setWindowTitle('budget')
|
||||||
self.setMinimumSize(800, 400)
|
self.setMinimumSize(800, 600)
|
||||||
|
|
||||||
self.pg = PostgresTab()
|
self.pg = PostgresTab()
|
||||||
self.categoryTab = CategoryTab(self)
|
self.categoryTab = CategoryTab(self)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
from PyQt6.QtWidgets import *
|
from PyQt6.QtWidgets import *
|
||||||
|
from PyQt6.QtCharts import *
|
||||||
from ._tab import TabPage
|
from ._tab import TabPage
|
||||||
from ._pg import PostgresTab
|
from ._pg import PostgresTab
|
||||||
from PyQt6.QtGui import QDoubleValidator
|
from PyQt6.QtGui import QDoubleValidator
|
||||||
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
class StatTab(TabPage):
|
class StatTab(TabPage):
|
||||||
|
@ -9,10 +11,73 @@ class StatTab(TabPage):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.initUI()
|
self.initUI()
|
||||||
self.pg = parent.pg
|
self.pg = parent.pg
|
||||||
self.rows = []
|
|
||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
|
# 按钮
|
||||||
|
self.outButton = QPushButton('Expense')
|
||||||
|
self.inButton = QPushButton('Income')
|
||||||
|
buttonLayout = QHBoxLayout()
|
||||||
|
buttonLayout.addWidget(self.outButton)
|
||||||
|
buttonLayout.addWidget(self.inButton)
|
||||||
|
|
||||||
|
# 饼状图
|
||||||
|
self.chart = QChart()
|
||||||
|
self.chart.setTitle('Month Statistics')
|
||||||
|
self.chart.setAnimationOptions(QChart.AnimationOption.SeriesAnimations)
|
||||||
|
chartLayout = QVBoxLayout()
|
||||||
|
chartLayout.addWidget(QChartView(self.chart))
|
||||||
|
|
||||||
|
leftLayout = QVBoxLayout()
|
||||||
|
leftLayout.addLayout(buttonLayout)
|
||||||
|
leftLayout.addLayout(chartLayout)
|
||||||
|
|
||||||
|
# 日历控件
|
||||||
|
self.calendar = QCalendarWidget()
|
||||||
|
self.calendar.setGridVisible(True)
|
||||||
|
# 日历点击事件
|
||||||
|
self.calendar.clicked.connect(self.onCalendarClicked)
|
||||||
|
# 切换月份事件
|
||||||
|
self.calendar.currentPageChanged.connect(self.onCalendarPageChanged)
|
||||||
|
|
||||||
|
calenderLayout = QHBoxLayout()
|
||||||
|
calenderLayout.addWidget(self.calendar)
|
||||||
|
|
||||||
|
statLayout = QHBoxLayout()
|
||||||
|
statLayout.addLayout(leftLayout)
|
||||||
|
statLayout.addLayout(calenderLayout)
|
||||||
|
self.setLayout(statLayout)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def onCalendarClicked(self, date):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def onXXXClicked(self):
|
|
||||||
pass
|
def onCalendarPageChanged(self, year, month):
|
||||||
|
print(year, month)
|
||||||
|
|
||||||
|
# 合计分类的交易量
|
||||||
|
self.pg.execute("SELECT c_id, sum(amount)::numeric::float8 FROM transaction WHERE c_id IS NOT NULL and \
|
||||||
|
time BETWEEN %s AND %s GROUP BY c_id ORDER BY c_id", \
|
||||||
|
(datetime.date(year, month, 1), datetime.date(year, month+1, 1),))
|
||||||
|
self.statData = self.pg.fetchall()
|
||||||
|
print(self.statData)
|
||||||
|
|
||||||
|
# 获取此月所有交易类别
|
||||||
|
self.pg.execute("SELECT c_id, meta->>'name' FROM category \
|
||||||
|
WHERE c_id in (SELECT c_id FROM transaction WHERE time between %s and %s GROUP BY c_id) \
|
||||||
|
ORDER BY c_id", \
|
||||||
|
(datetime.date(year, month, 1), datetime.date(year, month+1, 1),))
|
||||||
|
self.categoryData = self.pg.fetchall()
|
||||||
|
print(self.categoryData)
|
||||||
|
|
||||||
|
# 填充饼状图
|
||||||
|
self.chart.removeAllSeries()
|
||||||
|
series = QPieSeries()
|
||||||
|
for i in range(len(self.statData)):
|
||||||
|
series.append(self.categoryData[i][1], self.statData[i][1])
|
||||||
|
self.chart.addSeries(series)
|
||||||
|
|
||||||
|
def selected(self):
|
||||||
|
# 刷新图表
|
||||||
|
self.onCalendarPageChanged(self.calendar.yearShown(), self.calendar.monthShown())
|
||||||
|
|
|
@ -10,7 +10,6 @@ class TransTab(TabPage):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.initUI()
|
self.initUI()
|
||||||
self.pg = parent.pg
|
self.pg = parent.pg
|
||||||
self.rows = []
|
|
||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
# 创建顶部控件
|
# 创建顶部控件
|
||||||
|
@ -124,7 +123,104 @@ class TransTab(TabPage):
|
||||||
QMessageBox.critical(self, 'Error', str(e))
|
QMessageBox.critical(self, 'Error', str(e))
|
||||||
|
|
||||||
def onTransModifyClicked(self):
|
def onTransModifyClicked(self):
|
||||||
pass
|
# 获取当前选择的行
|
||||||
|
self.rows = self.transTable.selectionModel().selectedRows()
|
||||||
|
if len(self.rows) == 0:
|
||||||
|
QMessageBox.critical(self, 'Error', 'No row selected')
|
||||||
|
return
|
||||||
|
|
||||||
|
# 创建修改数据对话框
|
||||||
|
self.tDialog = QDialog(self)
|
||||||
|
self.tDialog.setWindowTitle('Modify Transaction')# 时间 金额 描述
|
||||||
|
timeLabel=QLabel("Time:")
|
||||||
|
timeLine=QLineEdit()
|
||||||
|
timeLine.setText(self.transData[self.rows[0].row()][4].strftime("%Y-%m-%d %H:%M:%S"))
|
||||||
|
|
||||||
|
amountLabel = QLabel("Amount:")
|
||||||
|
amountLine = QLineEdit()
|
||||||
|
num = self.transData[self.rows[0].row()][5]
|
||||||
|
# 去掉¥符号,考虑负值
|
||||||
|
if num[0] == '-':
|
||||||
|
num = num[2:]
|
||||||
|
num = '-' + num
|
||||||
|
else:
|
||||||
|
num = num[1:]
|
||||||
|
|
||||||
|
|
||||||
|
amountLine.setText(num)
|
||||||
|
# 只允许输入两位小数
|
||||||
|
amountLine.setValidator(QDoubleValidator(0.00, 999999999.99, 2))
|
||||||
|
|
||||||
|
descriptionLabel = QLabel("Description:")
|
||||||
|
descriptionLine = QLineEdit()
|
||||||
|
descriptionLine.setText(self.transData[self.rows[0].row()][6])
|
||||||
|
|
||||||
|
cButton = QPushButton("Confirm")
|
||||||
|
aButton = QPushButton("Abort")
|
||||||
|
buttonLayout = QHBoxLayout()
|
||||||
|
buttonLayout.addWidget(cButton)
|
||||||
|
buttonLayout.addWidget(aButton)
|
||||||
|
|
||||||
|
cButton.clicked.connect(self.tDialog.accept)
|
||||||
|
aButton.clicked.connect(self.tDialog.reject)
|
||||||
|
|
||||||
|
self.dialogLayout = QFormLayout()
|
||||||
|
self.dialogLayout.addRow(timeLabel, timeLine)
|
||||||
|
self.dialogLayout.addRow(amountLabel, amountLine)
|
||||||
|
self.dialogLayout.addRow(descriptionLabel, descriptionLine)
|
||||||
|
self.dialogLayout.addRow(buttonLayout)
|
||||||
|
self.dialogLayout.setSpacing(12)
|
||||||
|
self.dialogLayout.setContentsMargins(15, 15, 15, 15)
|
||||||
|
|
||||||
|
self.tDialog.setMinimumWidth(400)
|
||||||
|
self.tDialog.setLayout(self.dialogLayout)
|
||||||
|
|
||||||
|
if self.tDialog.exec() == QDialog.DialogCode.Accepted:
|
||||||
|
try:
|
||||||
|
# 若修改金额,则修改账户余额
|
||||||
|
if num != amountLine.text():
|
||||||
|
amount = float(amountLine.text())
|
||||||
|
amount = amount - float(num)
|
||||||
|
print(amount)
|
||||||
|
self.pg.execute("UPDATE account SET balance = balance + (%s::NUMERIC)::MONEY WHERE a_id = %s",\
|
||||||
|
(amount, self.transData[self.rows[0].row()][1],))
|
||||||
|
|
||||||
|
# 检测时间格式
|
||||||
|
time = timeLine.text()
|
||||||
|
time = datetime.datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
# 把 meta 取回来
|
||||||
|
self.pg.execute("SELECT meta FROM transaction WHERE t_id = %s", (self.transData[self.rows[0].row()][0],))
|
||||||
|
meta = self.pg.fetchall()[0][0]
|
||||||
|
meta = json.dumps(meta)
|
||||||
|
|
||||||
|
# 修改描述
|
||||||
|
meta = json.loads(meta)
|
||||||
|
meta["description"] = descriptionLine.text()
|
||||||
|
meta = json.dumps(meta)
|
||||||
|
|
||||||
|
|
||||||
|
# 修改数据, 使用JSONB
|
||||||
|
self.pg.execute("UPDATE transaction SET time = %s, amount = %s, meta = %s WHERE t_id = %s",\
|
||||||
|
(time, amountLine.text(), meta, self.transData[self.rows[0].row()][0],))
|
||||||
|
|
||||||
|
# 刷新表格
|
||||||
|
self.selected()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
QMessageBox.critical(self, 'Error', str(e))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue