06/05 Optimize app

This commit is contained in:
2026-06-05 09:15:39 -04:00
parent daba148562
commit deba20cf7e
2 changed files with 52 additions and 7 deletions
+22
View File
@@ -52,3 +52,25 @@ class TellerAccount(db.Model):
def __repr__(self):
return f'<TellerAccount {self.account_name} → PFM #{self.pfm_account_id}>'
class TellerSyncPreview(db.Model):
"""
Temporary server-side storage for sync preview data.
Replaces cookie-based session storage which has a 4 KB limit —
large accounts (100+ transactions) exceeded that limit and caused
silent data loss on the confirm step.
One row per teller_account_id; overwritten on each new sync preview.
"""
__tablename__ = 'teller_sync_previews'
id = db.Column(db.Integer, primary_key=True)
teller_account_id = db.Column(
db.Integer, db.ForeignKey('teller_accounts.id'),
nullable=False, unique=True, index=True,
)
data_json = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return f'<TellerSyncPreview account_id={self.teller_account_id}>'
+29 -6
View File
@@ -7,7 +7,7 @@ from flask import (Blueprint, render_template, redirect, url_for, flash,
request, jsonify, current_app, session)
from flask_login import login_required, current_user
from app.extensions import db
from app.models.teller_enrollment import TellerEnrollment, TellerAccount
from app.models.teller_enrollment import TellerEnrollment, TellerAccount, TellerSyncPreview
from app.models.account import Account
from app.services.teller_service import (
get_accounts, get_balance, sync_preview, import_transactions,
@@ -183,13 +183,14 @@ def sync_preview_view(teller_account_id):
flash(f'Sync failed: {e}', 'danger')
return redirect(url_for('teller.index'))
# Store preview in session for confirm step
session['teller_preview'] = [
# Store preview in DB (not session cookie — cookie limit is 4 KB;
# large accounts with 100+ transactions silently exceeded it).
preview_data = [
{
'teller_id': p['teller_id'],
'date': p['date'].isoformat(),
'transaction_type': p['transaction_type'],
'amount': p['amount'],
'amount': float(p['amount']),
'description': p['description'],
'account_id': p['account_id'],
'category_id': p['category_id'],
@@ -197,6 +198,19 @@ def sync_preview_view(teller_account_id):
}
for p in preview
]
# Upsert: one preview row per teller account (overwrite any stale preview)
existing_sp = TellerSyncPreview.query.filter_by(teller_account_id=teller_account_id).first()
if existing_sp:
existing_sp.data_json = json.dumps(preview_data)
existing_sp.created_at = __import__('datetime').datetime.utcnow()
sp = existing_sp
else:
sp = TellerSyncPreview(teller_account_id=teller_account_id,
data_json=json.dumps(preview_data))
db.session.add(sp)
db.session.commit()
# Only the tiny row ID goes into the session cookie
session['teller_preview_id'] = sp.id
session['teller_account_id'] = teller_account_id
from app.models.category import Category
@@ -213,13 +227,22 @@ def sync_preview_view(teller_account_id):
@login_required
def sync_confirm():
"""Import selected previewed transactions with optional type overrides."""
raw = session.pop('teller_preview', [])
preview_id = session.pop('teller_preview_id', None)
ta_id = session.pop('teller_account_id', None)
if not raw or not ta_id:
if not preview_id or not ta_id:
flash('No pending import. Please sync again.', 'warning')
return redirect(url_for('teller.index'))
sp = db.session.get(TellerSyncPreview, preview_id)
if not sp:
flash('Preview expired or already imported. Please sync again.', 'warning')
return redirect(url_for('teller.index'))
raw = json.loads(sp.data_json)
db.session.delete(sp)
db.session.commit()
ta = db.get_or_404(TellerAccount, ta_id)
selected_ids = set(request.form.getlist('selected'))