mirror of
https://github.com/elisiariocouto/leggen.git
synced 2025-12-13 14:52:16 +00:00
feat(frontend): adapt to composite key transaction structure
- Update Transaction interface to include stable transaction_id field - Modify TransactionsList to use stable transaction_id for React keys - Update API models to handle new transactionId field from database - Fix API routes to properly map transaction_id in responses - Update test mocks to include transactionId field - Ensure backward compatibility with internal_transaction_id This adapts the frontend to work with the new composite primary key (accountId, transactionId) structure that prevents duplicate transactions.
This commit is contained in:
@@ -267,10 +267,7 @@ export default function TransactionsList() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={
|
key={`${transaction.account_id}-${transaction.transaction_id}`}
|
||||||
transaction.internal_transaction_id ||
|
|
||||||
`${transaction.account_id}-${transaction.transaction_date}-${transaction.transaction_value}`
|
|
||||||
}
|
|
||||||
className="p-6 hover:bg-gray-50 transition-colors"
|
className="p-6 hover:bg-gray-50 transition-colors"
|
||||||
>
|
>
|
||||||
<div className="flex items-start justify-between">
|
<div className="flex items-start justify-between">
|
||||||
@@ -365,7 +362,7 @@ export default function TransactionsList() {
|
|||||||
isOpen={showRawModal}
|
isOpen={showRawModal}
|
||||||
onClose={handleCloseModal}
|
onClose={handleCloseModal}
|
||||||
rawTransaction={selectedTransaction?.raw_transaction}
|
rawTransaction={selectedTransaction?.raw_transaction}
|
||||||
transactionId={selectedTransaction?.internal_transaction_id || "unknown"}
|
transactionId={selectedTransaction?.transaction_id || "unknown"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ export interface RawTransactionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Transaction {
|
export interface Transaction {
|
||||||
internal_transaction_id: string | null;
|
transaction_id: string; // NEW: stable bank-provided transaction ID
|
||||||
|
internal_transaction_id: string | null; // OLD: unstable GoCardless ID
|
||||||
account_id: string;
|
account_id: string;
|
||||||
transaction_value: number;
|
transaction_value: number;
|
||||||
transaction_currency: string;
|
transaction_currency: string;
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ class AccountDetails(BaseModel):
|
|||||||
class Transaction(BaseModel):
|
class Transaction(BaseModel):
|
||||||
"""Transaction model"""
|
"""Transaction model"""
|
||||||
|
|
||||||
internal_transaction_id: Optional[str] = None
|
transaction_id: str # NEW: stable bank-provided transaction ID
|
||||||
|
internal_transaction_id: Optional[str] = None # OLD: unstable GoCardless ID
|
||||||
institution_id: str
|
institution_id: str
|
||||||
iban: Optional[str] = None
|
iban: Optional[str] = None
|
||||||
account_id: str
|
account_id: str
|
||||||
@@ -54,6 +55,7 @@ class Transaction(BaseModel):
|
|||||||
class TransactionSummary(BaseModel):
|
class TransactionSummary(BaseModel):
|
||||||
"""Transaction summary for lists"""
|
"""Transaction summary for lists"""
|
||||||
|
|
||||||
|
transaction_id: str # NEW: stable bank-provided transaction ID
|
||||||
internal_transaction_id: Optional[str] = None
|
internal_transaction_id: Optional[str] = None
|
||||||
date: datetime
|
date: datetime
|
||||||
description: str
|
description: str
|
||||||
|
|||||||
@@ -243,7 +243,8 @@ async def get_account_transactions(
|
|||||||
# Return simplified transaction summaries
|
# Return simplified transaction summaries
|
||||||
data = [
|
data = [
|
||||||
TransactionSummary(
|
TransactionSummary(
|
||||||
internal_transaction_id=txn["internalTransactionId"],
|
transaction_id=txn["transactionId"], # NEW: stable bank-provided ID
|
||||||
|
internal_transaction_id=txn.get("internalTransactionId"),
|
||||||
date=txn["transactionDate"],
|
date=txn["transactionDate"],
|
||||||
description=txn["description"],
|
description=txn["description"],
|
||||||
amount=txn["transactionValue"],
|
amount=txn["transactionValue"],
|
||||||
@@ -257,7 +258,8 @@ async def get_account_transactions(
|
|||||||
# Return full transaction details
|
# Return full transaction details
|
||||||
data = [
|
data = [
|
||||||
Transaction(
|
Transaction(
|
||||||
internal_transaction_id=txn["internalTransactionId"],
|
transaction_id=txn["transactionId"], # NEW: stable bank-provided ID
|
||||||
|
internal_transaction_id=txn.get("internalTransactionId"),
|
||||||
institution_id=txn["institutionId"],
|
institution_id=txn["institutionId"],
|
||||||
iban=txn["iban"],
|
iban=txn["iban"],
|
||||||
account_id=txn["accountId"],
|
account_id=txn["accountId"],
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ async def get_all_transactions(
|
|||||||
# Return simplified transaction summaries
|
# Return simplified transaction summaries
|
||||||
data = [
|
data = [
|
||||||
TransactionSummary(
|
TransactionSummary(
|
||||||
internal_transaction_id=txn["internalTransactionId"],
|
transaction_id=txn["transactionId"], # NEW: stable bank-provided ID
|
||||||
|
internal_transaction_id=txn.get("internalTransactionId"),
|
||||||
date=txn["transactionDate"],
|
date=txn["transactionDate"],
|
||||||
description=txn["description"],
|
description=txn["description"],
|
||||||
amount=txn["transactionValue"],
|
amount=txn["transactionValue"],
|
||||||
@@ -89,7 +90,8 @@ async def get_all_transactions(
|
|||||||
# Return full transaction details
|
# Return full transaction details
|
||||||
data = [
|
data = [
|
||||||
Transaction(
|
Transaction(
|
||||||
internal_transaction_id=txn["internalTransactionId"],
|
transaction_id=txn["transactionId"], # NEW: stable bank-provided ID
|
||||||
|
internal_transaction_id=txn.get("internalTransactionId"),
|
||||||
institution_id=txn["institutionId"],
|
institution_id=txn["institutionId"],
|
||||||
iban=txn["iban"],
|
iban=txn["iban"],
|
||||||
account_id=txn["accountId"],
|
account_id=txn["accountId"],
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class TestTransactionsAPI:
|
|||||||
"""Test successful retrieval of all transactions from database."""
|
"""Test successful retrieval of all transactions from database."""
|
||||||
mock_transactions = [
|
mock_transactions = [
|
||||||
{
|
{
|
||||||
|
"transactionId": "bank-txn-001", # NEW: stable bank-provided ID
|
||||||
"internalTransactionId": "txn-001",
|
"internalTransactionId": "txn-001",
|
||||||
"institutionId": "REVOLUT_REVOLT21",
|
"institutionId": "REVOLUT_REVOLT21",
|
||||||
"iban": "LT313250081177977789",
|
"iban": "LT313250081177977789",
|
||||||
@@ -24,9 +25,10 @@ class TestTransactionsAPI:
|
|||||||
"transactionCurrency": "EUR",
|
"transactionCurrency": "EUR",
|
||||||
"transactionStatus": "booked",
|
"transactionStatus": "booked",
|
||||||
"accountId": "test-account-123",
|
"accountId": "test-account-123",
|
||||||
"rawTransaction": {"some": "data"},
|
"rawTransaction": {"transactionId": "bank-txn-001", "some": "data"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"transactionId": "bank-txn-002", # NEW: stable bank-provided ID
|
||||||
"internalTransactionId": "txn-002",
|
"internalTransactionId": "txn-002",
|
||||||
"institutionId": "REVOLUT_REVOLT21",
|
"institutionId": "REVOLUT_REVOLT21",
|
||||||
"iban": "LT313250081177977789",
|
"iban": "LT313250081177977789",
|
||||||
@@ -36,7 +38,7 @@ class TestTransactionsAPI:
|
|||||||
"transactionCurrency": "EUR",
|
"transactionCurrency": "EUR",
|
||||||
"transactionStatus": "booked",
|
"transactionStatus": "booked",
|
||||||
"accountId": "test-account-123",
|
"accountId": "test-account-123",
|
||||||
"rawTransaction": {"other": "data"},
|
"rawTransaction": {"transactionId": "bank-txn-002", "other": "data"},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -73,6 +75,7 @@ class TestTransactionsAPI:
|
|||||||
"""Test retrieval of full transaction details from database."""
|
"""Test retrieval of full transaction details from database."""
|
||||||
mock_transactions = [
|
mock_transactions = [
|
||||||
{
|
{
|
||||||
|
"transactionId": "bank-txn-001", # NEW: stable bank-provided ID
|
||||||
"internalTransactionId": "txn-001",
|
"internalTransactionId": "txn-001",
|
||||||
"institutionId": "REVOLUT_REVOLT21",
|
"institutionId": "REVOLUT_REVOLT21",
|
||||||
"iban": "LT313250081177977789",
|
"iban": "LT313250081177977789",
|
||||||
@@ -82,7 +85,7 @@ class TestTransactionsAPI:
|
|||||||
"transactionCurrency": "EUR",
|
"transactionCurrency": "EUR",
|
||||||
"transactionStatus": "booked",
|
"transactionStatus": "booked",
|
||||||
"accountId": "test-account-123",
|
"accountId": "test-account-123",
|
||||||
"rawTransaction": {"some": "raw_data"},
|
"rawTransaction": {"transactionId": "bank-txn-001", "some": "raw_data"},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -105,6 +108,7 @@ class TestTransactionsAPI:
|
|||||||
assert len(data["data"]) == 1
|
assert len(data["data"]) == 1
|
||||||
|
|
||||||
transaction = data["data"][0]
|
transaction = data["data"][0]
|
||||||
|
assert transaction["transaction_id"] == "bank-txn-001" # NEW: check stable ID
|
||||||
assert transaction["internal_transaction_id"] == "txn-001"
|
assert transaction["internal_transaction_id"] == "txn-001"
|
||||||
assert transaction["institution_id"] == "REVOLUT_REVOLT21"
|
assert transaction["institution_id"] == "REVOLUT_REVOLT21"
|
||||||
assert transaction["iban"] == "LT313250081177977789"
|
assert transaction["iban"] == "LT313250081177977789"
|
||||||
@@ -116,6 +120,7 @@ class TestTransactionsAPI:
|
|||||||
"""Test getting transactions with various filters."""
|
"""Test getting transactions with various filters."""
|
||||||
mock_transactions = [
|
mock_transactions = [
|
||||||
{
|
{
|
||||||
|
"transactionId": "bank-txn-001", # NEW: stable bank-provided ID
|
||||||
"internalTransactionId": "txn-001",
|
"internalTransactionId": "txn-001",
|
||||||
"institutionId": "REVOLUT_REVOLT21",
|
"institutionId": "REVOLUT_REVOLT21",
|
||||||
"iban": "LT313250081177977789",
|
"iban": "LT313250081177977789",
|
||||||
@@ -125,7 +130,7 @@ class TestTransactionsAPI:
|
|||||||
"transactionCurrency": "EUR",
|
"transactionCurrency": "EUR",
|
||||||
"transactionStatus": "booked",
|
"transactionStatus": "booked",
|
||||||
"accountId": "test-account-123",
|
"accountId": "test-account-123",
|
||||||
"rawTransaction": {"some": "data"},
|
"rawTransaction": {"transactionId": "bank-txn-001", "some": "data"},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user