diff --git a/src/budget/_category.py b/src/budget/_category.py index 921ac4f..83b8939 100644 --- a/src/budget/_category.py +++ b/src/budget/_category.py @@ -28,9 +28,9 @@ class CategoryTab(TabPage): topLayout.addWidget(self.categoryAddButton) # 创建表格 - self.accountTable = QTableWidget() + self.categoryTable = QTableWidget() tableLayout = QVBoxLayout() - tableLayout.addWidget(self.accountTable) + tableLayout.addWidget(self.categoryTable) # 应用布局 categoryLayout = QVBoxLayout() diff --git a/src/budget/_hook.py b/src/budget/_hook.py deleted file mode 100644 index 60e2bc6..0000000 --- a/src/budget/_hook.py +++ /dev/null @@ -1,2 +0,0 @@ -from PyQt6.QtWidgets import * -from PyQt6.QtCore import * diff --git a/src/budget/_mw.py b/src/budget/_mw.py index 0cd12b4..41352c2 100644 --- a/src/budget/_mw.py +++ b/src/budget/_mw.py @@ -9,7 +9,7 @@ from ._stat import StatTab def initUI(self): self.setWindowTitle('budget') - self.setMinimumSize(800, 400) + self.setMinimumSize(800, 600) self.pg = PostgresTab() self.categoryTab = CategoryTab(self) diff --git a/src/budget/_stat.py b/src/budget/_stat.py index 8447ec3..1dd765b 100644 --- a/src/budget/_stat.py +++ b/src/budget/_stat.py @@ -1,7 +1,9 @@ from PyQt6.QtWidgets import * +from PyQt6.QtCharts import * from ._tab import TabPage from ._pg import PostgresTab from PyQt6.QtGui import QDoubleValidator +import datetime import json class StatTab(TabPage): @@ -9,10 +11,73 @@ class StatTab(TabPage): super().__init__() self.initUI() self.pg = parent.pg - self.rows = [] 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 - 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()) diff --git a/src/budget/_trans.py b/src/budget/_trans.py index d5ccf5f..a4b2453 100644 --- a/src/budget/_trans.py +++ b/src/budget/_trans.py @@ -10,7 +10,6 @@ class TransTab(TabPage): super().__init__() self.initUI() self.pg = parent.pg - self.rows = [] def initUI(self): # 创建顶部控件 @@ -124,7 +123,104 @@ class TransTab(TabPage): QMessageBox.critical(self, 'Error', str(e)) 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 + + + + + + + + +