06/03 Optimize codes, fix sync import transaction types
This commit is contained in:
@@ -181,17 +181,17 @@ def parse_transaction(teller_txn, pfm_account_id, category_id_map):
|
|||||||
Returns dict with keys matching Transaction model fields.
|
Returns dict with keys matching Transaction model fields.
|
||||||
|
|
||||||
Teller amounts:
|
Teller amounts:
|
||||||
- Positive = money leaving the account (expense / debit)
|
- Positive = money entering the account (income / credit)
|
||||||
- Negative = money entering the account (income / credit)
|
- Negative = money leaving the account (expense / debit)
|
||||||
"""
|
"""
|
||||||
amount_raw = float(teller_txn.get('amount', 0))
|
amount_raw = float(teller_txn.get('amount', 0))
|
||||||
# Teller: positive = outflow (expense), negative = inflow (income)
|
# Teller: positive = inflow/credit (income), negative = outflow/debit (expense)
|
||||||
if amount_raw > 0:
|
if amount_raw < 0:
|
||||||
txn_type = 'expense'
|
txn_type = 'expense'
|
||||||
amount = amount_raw
|
amount = abs(amount_raw)
|
||||||
else:
|
else:
|
||||||
txn_type = 'income'
|
txn_type = 'income'
|
||||||
amount = abs(amount_raw)
|
amount = amount_raw
|
||||||
|
|
||||||
description = teller_txn.get('description', '').strip() or 'Teller transaction'
|
description = teller_txn.get('description', '').strip() or 'Teller transaction'
|
||||||
# Use enriched counterparty name if available
|
# Use enriched counterparty name if available
|
||||||
@@ -287,7 +287,7 @@ def import_transactions(parsed_txns, teller_account):
|
|||||||
affected_accounts = set()
|
affected_accounts = set()
|
||||||
|
|
||||||
for p in parsed_txns:
|
for p in parsed_txns:
|
||||||
# Duplicate check: match on teller_id in notes OR date+amount+description
|
# Duplicate check: match on teller_id in notes
|
||||||
teller_id = p['teller_id']
|
teller_id = p['teller_id']
|
||||||
existing = Transaction.query.filter(
|
existing = Transaction.query.filter(
|
||||||
Transaction.notes.like(f'%{teller_id}%')
|
Transaction.notes.like(f'%{teller_id}%')
|
||||||
@@ -319,9 +319,24 @@ def import_transactions(parsed_txns, teller_account):
|
|||||||
teller_account.enrollment.last_synced_at = now
|
teller_account.enrollment.last_synced_at = now
|
||||||
if parsed_txns:
|
if parsed_txns:
|
||||||
teller_account.last_teller_txn_id = parsed_txns[0]['teller_id']
|
teller_account.last_teller_txn_id = parsed_txns[0]['teller_id']
|
||||||
from app.extensions import db as _db
|
db.session.commit()
|
||||||
_db.session.commit()
|
|
||||||
|
|
||||||
|
# Refresh balance from Teller live API (source of truth for linked accounts).
|
||||||
|
# Fall back to transaction-computed balance only if the API call fails.
|
||||||
|
if teller_account.pfm_account_id:
|
||||||
|
try:
|
||||||
|
bal_data = get_balance(teller_account.enrollment.access_token,
|
||||||
|
teller_account.teller_account_id)
|
||||||
|
available = float(bal_data.get('available') or bal_data.get('ledger') or 0)
|
||||||
|
ledger = float(bal_data.get('ledger') or bal_data.get('available') or 0)
|
||||||
|
is_credit = teller_account.pfm_account.account_type == 'credit_card'
|
||||||
|
teller_account.pfm_account.balance = -abs(ledger) if is_credit else available
|
||||||
|
db.session.commit()
|
||||||
|
log.info('[teller] balance refreshed after sync for %s: %.2f',
|
||||||
|
teller_account.account_name, float(teller_account.pfm_account.balance))
|
||||||
|
except Exception as e:
|
||||||
|
log.warning('[teller] live balance unavailable after sync, falling back to '
|
||||||
|
'calc_balance: %s', e)
|
||||||
for account_id in affected_accounts:
|
for account_id in affected_accounts:
|
||||||
calc_balance(account_id)
|
calc_balance(account_id)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user