diff options
Diffstat (limited to 'cashflow.cpp')
| -rw-r--r-- | cashflow.cpp | 399 |
1 files changed, 232 insertions, 167 deletions
diff --git a/cashflow.cpp b/cashflow.cpp index f302110..e157a8f 100644 --- a/cashflow.cpp +++ b/cashflow.cpp @@ -2,6 +2,7 @@ #include "ui_cashflow.h" #include "settingsdialog.h" #include <QMessageBox> +#include <QDebug> #include <QDir> #include <QStandardPaths> #include <QFontDialog> @@ -34,6 +35,10 @@ CashFlow::CashFlow(QWidget *parent) QMessageBox::critical(this, "Database Error", "Failed to open default database: " + database->lastError()); return; } + + // Regenerate all projections on startup to ensure they're current + database->regenerateAllProjections(); + refreshView(); // Refresh to show new projection IDs } CashFlow::~CashFlow() @@ -70,6 +75,16 @@ void CashFlow::setupConnections() { connect(ui->saveBtn, &QPushButton::clicked, this, &CashFlow::onSaveTransaction); connect(ui->newBtn, &QPushButton::clicked, this, &CashFlow::onNewTransaction); connect(ui->deleteBtn, &QPushButton::clicked, this, &CashFlow::onDeleteTransaction); + connect(ui->adjustmentBtn, &QPushButton::clicked, this, &CashFlow::onCreateAdjustment); + + // Transaction type change - grey out fields for reconciliation + connect(ui->entryTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) { + bool isReconciliation = (index == 2); // Reconciliation is index 2 + ui->entryCategoryCombo->setEnabled(!isReconciliation); + ui->entryRecurringCombo->setEnabled(!isReconciliation); + ui->entryOccurrenceEdit->setEnabled(!isReconciliation); + ui->adjustmentBtn->setVisible(false); // Hide until we load a reconciliation + }); // Transaction entry recurring rule linking connect(ui->entryRecurringCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CashFlow::onRecurringRuleChanged); @@ -207,19 +222,24 @@ void CashFlow::refreshTransactionTable() { // Store ID in first column's data for retrieval later QTableWidgetItem *dateItem = new QTableWidgetItem(t.date.toString("MM/dd/yy")); dateItem->setData(Qt::UserRole, t.id); - // Store full transaction for projected items (id == -1) - if (t.id == -1) { - dateItem->setData(Qt::UserRole + 1, QVariant::fromValue(t)); - } dateItem->setFlags(dateItem->flags() & ~Qt::ItemIsEditable); ui->transactionTable->setItem(row, 0, dateItem); + // For reconciliation rows, show expected balance in amount column, variance in balance column + double displayAmount = t.amount; + double displayBalance = runningBalance; + + if (t.type == TransactionType::Reconciliation) { + displayAmount = t.expectedBalance; // Show what bank says + displayBalance = t.expectedBalance - t.calculatedBalance; // Show variance + } + // Format amount with color, right-align, monospace - QTableWidgetItem *amountItem = new QTableWidgetItem(QString("$%1").arg(formatCurrency(t.amount))); + QTableWidgetItem *amountItem = new QTableWidgetItem(QString("$%1").arg(formatCurrency(displayAmount))); amountItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); amountItem->setFont(currentAmountFont); amountItem->setFlags(amountItem->flags() & ~Qt::ItemIsEditable); - if (t.amount < 0) { + if (displayAmount < 0) { amountItem->setForeground(QColor(200, 0, 0)); } else { amountItem->setForeground(QColor(0, 150, 0)); @@ -227,11 +247,11 @@ void CashFlow::refreshTransactionTable() { ui->transactionTable->setItem(row, 1, amountItem); // Format balance with right-align, monospace - QTableWidgetItem *balanceItem = new QTableWidgetItem(QString("$%1").arg(formatCurrency(runningBalance))); + QTableWidgetItem *balanceItem = new QTableWidgetItem(QString("$%1").arg(formatCurrency(displayBalance))); balanceItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); balanceItem->setFont(currentAmountFont); balanceItem->setFlags(balanceItem->flags() & ~Qt::ItemIsEditable); - if (runningBalance < 0) { + if (displayBalance < 0) { balanceItem->setForeground(QColor(200, 0, 0)); } ui->transactionTable->setItem(row, 2, balanceItem); @@ -244,18 +264,35 @@ void CashFlow::refreshTransactionTable() { categoryItem->setFlags(categoryItem->flags() & ~Qt::ItemIsEditable); ui->transactionTable->setItem(row, 4, categoryItem); - QTableWidgetItem *descItem = new QTableWidgetItem(t.description); + // For reconciliation, show calculated status in description + QString displayDescription = t.description; + if (t.type == TransactionType::Reconciliation) { + double variance = t.expectedBalance - t.calculatedBalance; + QString status = (qAbs(variance) < 0.01) ? "Balanced" : QString("Out of balance by $%1").arg(formatCurrency(variance)); + displayDescription = t.description.isEmpty() ? status : QString("%1 - %2").arg(t.description, status); + } + + QTableWidgetItem *descItem = new QTableWidgetItem(displayDescription); descItem->setFlags(descItem->flags() & ~Qt::ItemIsEditable); ui->transactionTable->setItem(row, 5, descItem); - QTableWidgetItem *typeItem = new QTableWidgetItem( - t.type == TransactionType::Actual ? "Actual" : "Estimated"); + QString typeLabel = "Estimated"; + if (t.type == TransactionType::Actual) typeLabel = "Actual"; + else if (t.type == TransactionType::Reconciliation) typeLabel = "Reconciliation"; + + QTableWidgetItem *typeItem = new QTableWidgetItem(typeLabel); typeItem->setFlags(typeItem->flags() & ~Qt::ItemIsEditable); ui->transactionTable->setItem(row, 6, typeItem); - // Color code estimated vs actual - QColor rowColor = t.type == TransactionType::Actual ? - QColor(200, 255, 200) : QColor(255, 255, 200); + // Color code: Actual=green, Estimated=yellow, Reconciliation=red if mismatch, green if balanced + QColor rowColor; + if (t.type == TransactionType::Reconciliation) { + double variance = qAbs(t.expectedBalance - t.calculatedBalance); + rowColor = (variance < 0.01) ? QColor(200, 255, 200) : QColor(255, 200, 200); + } else { + rowColor = t.type == TransactionType::Actual ? QColor(200, 255, 200) : QColor(255, 255, 200); + } + for (int col = 0; col < 7; col++) { if (ui->transactionTable->item(row, col)) { ui->transactionTable->item(row, col)->setBackground(rowColor); @@ -456,14 +493,8 @@ QList<Transaction> CashFlow::getAllTransactionsInRange() { accountFilter = "All Accounts"; } - // Get actual transactions from database - QList<Transaction> actualTransactions = database->getTransactions(startDate, endDate); - - // Generate projected transactions from recurring rules - QList<Transaction> projectedTransactions = generateProjectedTransactions(); - - // Combine - QList<Transaction> allTransactions = actualTransactions + projectedTransactions; + // Get all transactions from database (includes both actual and projected) + QList<Transaction> allTransactions = database->getTransactions(startDate, endDate); // Filter by account if not "All Accounts" if (accountFilter != "All Accounts") { @@ -476,10 +507,15 @@ QList<Transaction> CashFlow::getAllTransactionsInRange() { allTransactions = filtered; } - // Sort by date, then by sort_order, then credits before debits + // Sort by date, then reconciliation always last, then by sort_order, then credits before debits std::sort(allTransactions.begin(), allTransactions.end(), [](const Transaction &a, const Transaction &b) { if (a.date != b.date) return a.date < b.date; + + // Reconciliation transactions always sort LAST on their date + if (a.type == TransactionType::Reconciliation && b.type != TransactionType::Reconciliation) return false; + if (a.type != TransactionType::Reconciliation && b.type == TransactionType::Reconciliation) return true; + if (a.sortOrder != b.sortOrder) return a.sortOrder < b.sortOrder; // Credits (positive amounts) before debits (negative amounts) return a.amount > b.amount; @@ -488,116 +524,11 @@ QList<Transaction> CashFlow::getAllTransactionsInRange() { return allTransactions; } -QList<Transaction> CashFlow::generateProjectedTransactions() { - QList<Transaction> projections; - QList<RecurringRule> rules = database->getAllRecurringRules(); - - QDate startDate = ui->dateFromEdit->date(); - QDate endDate = ui->dateToEdit->date(); - - // Load all actual transactions with recurring_id (converted projections) - QList<Transaction> actualTransactions = database->getAllTransactions(); - QSet<QString> existingOccurrences; // recurring_id:occurrence_key pairs - for (const Transaction &t : actualTransactions) { - if (t.recurringId != -1 && !t.occurrenceKey.isEmpty()) { - existingOccurrences.insert(QString("%1:%2").arg(t.recurringId).arg(t.occurrenceKey)); - } - } - - for (const RecurringRule &rule : rules) { - QDate currentDate = rule.startDate > startDate ? rule.startDate : startDate; - - // Align to proper day based on frequency - if (rule.frequency == RecurrenceFrequency::Weekly || rule.frequency == RecurrenceFrequency::BiWeekly) { - // Find next occurrence of the specified day of week - while (currentDate <= endDate && currentDate.dayOfWeek() != rule.dayOfWeek) { - currentDate = currentDate.addDays(1); - } - } else if (rule.frequency == RecurrenceFrequency::Monthly) { - // Set to the specified day of month - int targetDay = qMin(rule.dayOfMonth, currentDate.daysInMonth()); - currentDate = QDate(currentDate.year(), currentDate.month(), targetDay); - if (currentDate < startDate) { - currentDate = currentDate.addMonths(1); - targetDay = qMin(rule.dayOfMonth, currentDate.daysInMonth()); - currentDate = QDate(currentDate.year(), currentDate.month(), targetDay); - } - } - - int count = 0; - while (currentDate <= endDate) { - if (rule.occurrences != -1 && count >= rule.occurrences) { - break; - } - - if (rule.endDate.isValid() && currentDate > rule.endDate) { - break; - } - - // Generate occurrence key based on frequency - QString occurrenceKey; - if (rule.frequency == RecurrenceFrequency::Daily) { - occurrenceKey = currentDate.toString("yyyy-MM-dd"); - } else if (rule.frequency == RecurrenceFrequency::Weekly || rule.frequency == RecurrenceFrequency::BiWeekly) { - occurrenceKey = QString("%1-W%2").arg(currentDate.year()).arg(currentDate.weekNumber(), 2, 10, QChar('0')); - } else if (rule.frequency == RecurrenceFrequency::Monthly) { - occurrenceKey = currentDate.toString("yyyy-MM"); - } else if (rule.frequency == RecurrenceFrequency::Yearly) { - occurrenceKey = QString::number(currentDate.year()); - } - - // Skip if actual already exists for this occurrence - QString occurrenceCheck = QString("%1:%2").arg(rule.id).arg(occurrenceKey); - if (existingOccurrences.contains(occurrenceCheck)) { - // Actual exists, skip this projection - } else { - Transaction t; - t.id = -1; // Projected transactions have no ID - t.date = currentDate; - t.amount = rule.amount; - t.account = rule.account; - t.category = rule.category; - t.description = rule.description + " (projected)"; - t.type = TransactionType::Estimated; - t.recurringId = rule.id; - t.occurrenceKey = occurrenceKey; - t.reconciled = false; - - projections.append(t); - } - count++; - - // Calculate next occurrence - switch (rule.frequency) { - case RecurrenceFrequency::Daily: - currentDate = currentDate.addDays(1); - break; - case RecurrenceFrequency::Weekly: - currentDate = currentDate.addDays(7); - break; - case RecurrenceFrequency::BiWeekly: - currentDate = currentDate.addDays(14); - break; - case RecurrenceFrequency::Monthly: { - currentDate = currentDate.addMonths(1); - int targetDay = qMin(rule.dayOfMonth, currentDate.daysInMonth()); - currentDate = QDate(currentDate.year(), currentDate.month(), targetDay); - break; - } - case RecurrenceFrequency::Yearly: - currentDate = currentDate.addYears(1); - break; - default: - currentDate = endDate.addDays(1); // Exit loop - break; - } - } - } - - return projections; -} - void CashFlow::onDateRangeChanged() { + // Save date range to settings + database->setSetting("date_from", ui->dateFromEdit->date().toString(Qt::ISODate)); + database->setSetting("date_to", ui->dateToEdit->date().toString(Qt::ISODate)); + refreshView(); } @@ -614,26 +545,14 @@ void CashFlow::onTransactionSelected() { int row = selected[0]->row(); int id = ui->transactionTable->item(row, 0)->data(Qt::UserRole).toInt(); - // If it's a projected transaction (id = -1), load it for editing - if (id == -1) { - QVariant projectedData = ui->transactionTable->item(row, 0)->data(Qt::UserRole + 1); - if (projectedData.canConvert<Transaction>()) { - Transaction t = projectedData.value<Transaction>(); - currentTransactionId = -1; // Will create new actual when saved - currentProjectedTransaction = t; // Store for conversion - loadTransactionToEntry(t); - ui->entryStatusLabel->setText("(Converting Projection to Actual)"); - } - return; - } - // Load from database QList<Transaction> allTrans = database->getAllTransactions(); for (const Transaction &t : allTrans) { if (t.id == id) { currentTransactionId = id; loadTransactionToEntry(t); - ui->entryStatusLabel->setText(QString("Editing ID: %1").arg(id)); + QString typeLabel = (t.type == TransactionType::Estimated) ? "Estimated" : "Actual"; + ui->entryStatusLabel->setText(QString("Editing ID: %1 (%2)").arg(id).arg(typeLabel)); return; } } @@ -664,22 +583,29 @@ void CashFlow::onSaveTransaction() { t.account = ui->entryAccountCombo->currentText(); t.category = ui->entryCategoryCombo->currentText(); t.description = ui->entryDescriptionEdit->text(); - t.type = ui->entryTypeCombo->currentText() == "Actual" ? TransactionType::Actual : TransactionType::Estimated; + + QString typeText = ui->entryTypeCombo->currentText(); + if (typeText == "Actual") t.type = TransactionType::Actual; + else if (typeText == "Reconciliation") t.type = TransactionType::Reconciliation; + else t.type = TransactionType::Estimated; + + // If this is a reconciliation checkpoint, calculate the variance + if (t.type == TransactionType::Reconciliation) { + // amount field holds the expected balance from bank + t.expectedBalance = t.amount; + // Calculate what we think the balance should be + t.calculatedBalance = calculateBalanceUpTo(t.date, t.account); + // Don't overwrite user's description - it's saved as-is + // Category is irrelevant for reconciliation + t.category = ""; + t.amount = 0; // Reconciliation rows don't affect balance + } // Check if user manually linked to a recurring rule int manualRuleId = ui->entryRecurringCombo->currentData().toInt(); QString manualOccurrenceKey = ui->entryOccurrenceEdit->text().trimmed(); - // Check if we're converting a projection to actual - if (currentTransactionId == -1 && currentProjectedTransaction.recurringId != -1) { - // Converting projection - keep recurring link and store expected values - t.recurringId = currentProjectedTransaction.recurringId; - t.occurrenceKey = currentProjectedTransaction.occurrenceKey; - t.expectedAmount = currentProjectedTransaction.amount; - t.expectedDate = currentProjectedTransaction.date; - t.reconciled = true; - t.type = TransactionType::Actual; // Force to actual when converting - } else if (manualRuleId != -1 && !manualOccurrenceKey.isEmpty()) { + if (manualRuleId != -1 && !manualOccurrenceKey.isEmpty()) { // User manually linked to recurring rule t.recurringId = manualRuleId; t.occurrenceKey = manualOccurrenceKey; @@ -693,7 +619,7 @@ void CashFlow::onSaveTransaction() { } } } else if (currentTransactionId != -1) { - // Editing existing transaction - load from database to preserve reconciliation fields + // Editing existing transaction - preserve existing reconciliation fields QList<Transaction> allTrans = database->getAllTransactions(); for (const Transaction &existing : allTrans) { if (existing.id == currentTransactionId) { @@ -702,6 +628,16 @@ void CashFlow::onSaveTransaction() { t.expectedAmount = existing.expectedAmount; t.expectedDate = existing.expectedDate; t.reconciled = existing.reconciled; + // If user is converting Estimated to Actual, mark as reconciled + if (existing.type == TransactionType::Estimated && t.type == TransactionType::Actual) { + t.reconciled = true; + if (t.expectedAmount == 0) { + t.expectedAmount = existing.amount; // Store original projected amount + } + if (!t.expectedDate.isValid()) { + t.expectedDate = existing.date; // Store original projected date + } + } break; } } @@ -728,6 +664,9 @@ void CashFlow::onSaveTransaction() { } if (success) { + // Recalculate all reconciliation checkpoints since balances may have changed + recalculateAllReconciliations(); + ui->entryStatusLabel->setText("Saved!"); refreshView(); } else { @@ -737,7 +676,6 @@ void CashFlow::onSaveTransaction() { void CashFlow::onNewTransaction() { clearTransactionEntry(); - currentProjectedTransaction = Transaction(); // Reset projected transaction ui->entryDateEdit->setDate(QDate::currentDate()); ui->entryDateEdit->setFocus(); } @@ -751,6 +689,8 @@ void CashFlow::onDeleteTransaction() { if (QMessageBox::question(this, "Confirm Delete", QString("Delete transaction ID %1?").arg(currentTransactionId)) == QMessageBox::Yes) { if (database->deleteTransaction(currentTransactionId)) { + // Recalculate all reconciliation checkpoints since balances may have changed + recalculateAllReconciliations(); clearTransactionEntry(); refreshView(); } else { @@ -759,6 +699,61 @@ void CashFlow::onDeleteTransaction() { } } +void CashFlow::onCreateAdjustment() { + // Get the current reconciliation details + if (currentTransactionId == -1) return; + + QList<Transaction> allTrans = database->getAllTransactions(); + Transaction recon; + bool found = false; + + for (const Transaction &t : allTrans) { + if (t.id == currentTransactionId && t.type == TransactionType::Reconciliation) { + recon = t; + found = true; + break; + } + } + + if (!found) return; + + double variance = recon.expectedBalance - recon.calculatedBalance; + + QString msg = QString("Create an adjustment transaction for $%1 to match the bank balance?\n\n" + "Bank says: $%2\n" + "We calculate: $%3\n" + "Adjustment needed: $%4") + .arg(formatCurrency(qAbs(variance))) + .arg(formatCurrency(recon.expectedBalance)) + .arg(formatCurrency(recon.calculatedBalance)) + .arg(formatCurrency(variance)); + + if (QMessageBox::question(this, "Create Adjustment", msg) == QMessageBox::Yes) { + // Create adjustment transaction on the same date, same account + Transaction adj; + adj.id = -1; + adj.date = recon.date; + adj.amount = variance; + adj.account = recon.account; + adj.category = "Adjustment"; + adj.description = "Balance adjustment to match bank statement"; + adj.type = TransactionType::Actual; + adj.recurringId = -1; + adj.reconciled = false; + adj.sortOrder = 0; // Doesn't matter - reconciliation always sorts last + + if (database->addTransaction(adj)) { + // Recalculate reconciliations and refresh + recalculateAllReconciliations(); + refreshView(); + QMessageBox::information(this, "Success", "Adjustment transaction created."); + ui->adjustmentBtn->setVisible(false); // Hide button since we're now balanced + } else { + QMessageBox::critical(this, "Error", "Failed to create adjustment: " + database->lastError()); + } + } +} + void CashFlow::onRecurringSelected() { QList<QTableWidgetItem*> selected = ui->recurringTable->selectedItems(); if (selected.isEmpty()) { @@ -819,8 +814,20 @@ void CashFlow::onSaveRecurring() { bool success; if (currentRecurringId == -1) { success = database->addRecurringRule(r); + if (success) { + // Get the newly created rule ID to regenerate projections + QList<RecurringRule> rules = database->getAllRecurringRules(); + if (!rules.isEmpty()) { + RecurringRule newRule = rules.last(); + database->regenerateProjectionsForRule(newRule); + } + } } else { success = database->updateRecurringRule(r); + if (success) { + // Regenerate projections for updated rule + database->regenerateProjectionsForRule(r); + } } if (success) { @@ -844,7 +851,10 @@ void CashFlow::onDeleteRecurring() { } if (QMessageBox::question(this, "Confirm Delete", - "Delete this recurring rule?") == QMessageBox::Yes) { + "Delete this recurring rule and all its future projections?") == QMessageBox::Yes) { + // Delete future projections first + database->deleteProjectionsForRule(currentRecurringId); + // Then delete the rule if (database->deleteRecurringRule(currentRecurringId)) { clearRecurringEntry(); refreshView(); @@ -881,11 +891,19 @@ void CashFlow::loadTransactionToEntry(const Transaction &t) { ui->entryOccurrenceEdit->blockSignals(true); ui->entryDateEdit->setDate(t.date); - ui->entryAmountSpin->setValue(t.amount); + + // For reconciliation rows, load the expected balance into amount field + double loadAmount = (t.type == TransactionType::Reconciliation) ? t.expectedBalance : t.amount; + ui->entryAmountSpin->setValue(loadAmount); + ui->entryAccountCombo->setCurrentText(t.account); ui->entryCategoryCombo->setCurrentText(t.category); ui->entryDescriptionEdit->setText(t.description); - ui->entryTypeCombo->setCurrentIndex(t.type == TransactionType::Actual ? 1 : 0); + + int typeIndex = 0; // Estimated + if (t.type == TransactionType::Actual) typeIndex = 1; + else if (t.type == TransactionType::Reconciliation) typeIndex = 2; + ui->entryTypeCombo->setCurrentIndex(typeIndex); // Set recurring rule link if present if (t.recurringId != -1) { @@ -913,6 +931,14 @@ void CashFlow::loadTransactionToEntry(const Transaction &t) { ui->entryRecurringCombo->blockSignals(false); ui->entryOccurrenceEdit->blockSignals(false); + // Show adjustment button if this is a reconciliation that's out of balance + if (t.type == TransactionType::Reconciliation) { + double variance = qAbs(t.expectedBalance - t.calculatedBalance); + ui->adjustmentBtn->setVisible(variance >= 0.01); + } else { + ui->adjustmentBtn->setVisible(false); + } + updateAmountColors(); } @@ -977,10 +1003,20 @@ void CashFlow::loadSettings() { bool showAccountBalances = database->getSetting("show_account_balances", "0").toInt(); weekStartDay = database->getSetting("week_start_day", "1").toInt(); + // Load date range + QDate today = QDate::currentDate(); + QString dateFromStr = database->getSetting("date_from", ""); + QString dateToStr = database->getSetting("date_to", ""); + + QDate dateFrom = dateFromStr.isEmpty() ? QDate(today.year(), today.month(), 1) : QDate::fromString(dateFromStr, Qt::ISODate); + QDate dateTo = dateToStr.isEmpty() ? today.addMonths(3) : QDate::fromString(dateToStr, Qt::ISODate); + // Apply to member variables and main UI currentAmountFont = QFont(fontFamily, fontSize); ui->periodCombo->setCurrentIndex(defaultPeriod); ui->showAccountBalancesCheck->setChecked(showAccountBalances); + ui->dateFromEdit->setDate(dateFrom); + ui->dateToEdit->setDate(dateTo); } QString CashFlow::formatCurrency(double amount) const { @@ -988,6 +1024,40 @@ QString CashFlow::formatCurrency(double amount) const { return locale.toString(amount, 'f', 2); } +double CashFlow::calculateBalanceUpTo(const QDate &date, const QString &account) { + QList<Transaction> allTrans = database->getAllTransactions(); + double balance = 0.0; + + // Sort by date to ensure proper ordering + std::sort(allTrans.begin(), allTrans.end(), [](const Transaction &a, const Transaction &b) { + if (a.date != b.date) return a.date < b.date; + return a.sortOrder < b.sortOrder; + }); + + for (const Transaction &t : allTrans) { + if (t.date > date) continue; + if (!account.isEmpty() && t.account != account) continue; + if (t.type == TransactionType::Reconciliation) continue; // Don't count reconciliation rows + + balance += t.amount; + } + + return balance; +} + +void CashFlow::recalculateAllReconciliations() { + QList<Transaction> allTrans = database->getAllTransactions(); + + for (Transaction &t : allTrans) { + if (t.type == TransactionType::Reconciliation) { + // Recalculate the calculated balance + t.calculatedBalance = calculateBalanceUpTo(t.date, t.account); + // Update in database + database->updateTransaction(t); + } + } +} + bool CashFlow::openDatabase(const QString &filePath) { if (database->open(filePath)) { currentFilePath = filePath; @@ -996,11 +1066,6 @@ bool CashFlow::openDatabase(const QString &filePath) { loadSettings(); - // Set default date range (current month to 3 months out) - QDate today = QDate::currentDate(); - ui->dateFromEdit->setDate(QDate(today.year(), today.month(), 1)); - ui->dateToEdit->setDate(today.addMonths(3)); - clearTransactionEntry(); clearRecurringEntry(); refreshView(); |
