mirror of
https://github.com/elisiariocouto/leggen.git
synced 2025-12-13 20:42:39 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8228974c0c | ||
|
|
848eccb35b | ||
|
|
25747d7d37 | ||
|
|
b7d6cf8128 | ||
|
|
6589c2dd66 |
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -143,19 +143,19 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
- name: Install git-cliff
|
||||
run: |
|
||||
wget -qO- https://github.com/orhun/git-cliff/releases/latest/download/git-cliff-2.10.0-x86_64-unknown-linux-gnu.tar.gz | tar xz
|
||||
sudo mv git-cliff-*/git-cliff /usr/local/bin/
|
||||
|
||||
|
||||
- name: Generate release notes
|
||||
id: release_notes
|
||||
run: |
|
||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
||||
git-cliff --current >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
|
||||
42
CHANGELOG.md
42
CHANGELOG.md
@@ -1,4 +1,46 @@
|
||||
|
||||
## 2025.9.17 (2025/09/18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **api:** Prevent duplicate notifications for existing transactions during sync. ([25747d7d](https://github.com/elisiariocouto/leggen/commit/25747d7d372e291090764a6814f9d8d0b76aea3b))
|
||||
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- Format files. ([848eccb3](https://github.com/elisiariocouto/leggen/commit/848eccb35b910c8121d15611547dca8da0b12756))
|
||||
|
||||
|
||||
|
||||
## 2025.9.17 (2025/09/18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **api:** Prevent duplicate notifications for existing transactions during sync. ([25747d7d](https://github.com/elisiariocouto/leggen/commit/25747d7d372e291090764a6814f9d8d0b76aea3b))
|
||||
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- Format files. ([848eccb3](https://github.com/elisiariocouto/leggen/commit/848eccb35b910c8121d15611547dca8da0b12756))
|
||||
|
||||
|
||||
|
||||
## 2025.9.16 (2025/09/18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **frontend:** Add iOS safe area support for PWA sticky header ([6589c2dd](https://github.com/elisiariocouto/leggen/commit/6589c2dd666f8605cf6d1bf9ad7277734d4cd302))
|
||||
|
||||
|
||||
|
||||
## 2025.9.16 (2025/09/18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **frontend:** Add iOS safe area support for PWA sticky header ([6589c2dd](https://github.com/elisiariocouto/leggen/commit/6589c2dd666f8605cf6d1bf9ad7277734d4cd302))
|
||||
|
||||
|
||||
|
||||
## 2025.9.15 (2025/09/18)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
<TileColor>#3B82F6</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
</browserconfig>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: /sitemap.xml
|
||||
Sitemap: /sitemap.xml
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"preset": "minimal-2023",
|
||||
"images": ["public/favicon.svg"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function Header({ setSidebarOpen }: HeaderProps) {
|
||||
});
|
||||
|
||||
return (
|
||||
<header className="lg:static sticky top-0 z-50 bg-card shadow-sm border-b border-border">
|
||||
<header className="lg:static sticky top-0 z-50 bg-card shadow-sm border-b border-border pt-safe-top">
|
||||
<div className="flex items-center justify-between h-16 px-6">
|
||||
<div className="flex items-center">
|
||||
<button
|
||||
|
||||
@@ -33,11 +33,11 @@ export function PWAInstallPrompt({ onInstall }: PWAPromptProps) {
|
||||
try {
|
||||
await deferredPrompt.prompt();
|
||||
const { outcome } = await deferredPrompt.userChoice;
|
||||
|
||||
|
||||
if (outcome === "accepted") {
|
||||
onInstall?.();
|
||||
}
|
||||
|
||||
|
||||
setDeferredPrompt(null);
|
||||
setShowPrompt(false);
|
||||
} catch (error) {
|
||||
@@ -153,4 +153,4 @@ export function PWAUpdatePrompt({ updateAvailable, onUpdate }: PWAUpdatePromptPr
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,4 @@ export function usePWA(): PWAUpdate {
|
||||
updateAvailable,
|
||||
updateSW,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* iOS Safe Area Support for PWA */
|
||||
--safe-area-inset-top: env(safe-area-inset-top, 0px);
|
||||
--safe-area-inset-right: env(safe-area-inset-right, 0px);
|
||||
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
|
||||
--safe-area-inset-left: env(safe-area-inset-left, 0px);
|
||||
}
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
|
||||
@@ -9,6 +9,12 @@ export default {
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
},
|
||||
spacing: {
|
||||
'safe-top': 'var(--safe-area-inset-top)',
|
||||
'safe-bottom': 'var(--safe-area-inset-bottom)',
|
||||
'safe-left': 'var(--safe-area-inset-left)',
|
||||
'safe-right': 'var(--safe-area-inset-right)',
|
||||
},
|
||||
colors: {
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
|
||||
@@ -693,7 +693,7 @@ class DatabaseService:
|
||||
|
||||
# Add the display_name column
|
||||
cursor.execute("""
|
||||
ALTER TABLE accounts
|
||||
ALTER TABLE accounts
|
||||
ADD COLUMN display_name TEXT
|
||||
""")
|
||||
|
||||
@@ -857,6 +857,14 @@ class DatabaseService:
|
||||
|
||||
for transaction in transactions:
|
||||
try:
|
||||
# Check if transaction already exists before insertion
|
||||
cursor.execute(
|
||||
"""SELECT COUNT(*) FROM transactions
|
||||
WHERE accountId = ? AND transactionId = ?""",
|
||||
(transaction["accountId"], transaction["transactionId"]),
|
||||
)
|
||||
exists = cursor.fetchone()[0] > 0
|
||||
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
@@ -873,7 +881,11 @@ class DatabaseService:
|
||||
json.dumps(transaction["rawTransaction"]),
|
||||
),
|
||||
)
|
||||
new_transactions.append(transaction)
|
||||
|
||||
# Only add to new_transactions if it didn't exist before
|
||||
if not exists:
|
||||
new_transactions.append(transaction)
|
||||
|
||||
except sqlite3.IntegrityError as e:
|
||||
logger.warning(
|
||||
f"Failed to insert transaction {transaction.get('transactionId')}: {e}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "leggen"
|
||||
version = "2025.9.15"
|
||||
version = "2025.9.17"
|
||||
description = "An Open Banking CLI"
|
||||
authors = [{ name = "Elisiário Couto", email = "elisiario@couto.io" }]
|
||||
requires-python = "~=3.13.0"
|
||||
|
||||
@@ -324,6 +324,8 @@ class TestDatabaseService:
|
||||
with patch("sqlite3.connect") as mock_connect:
|
||||
mock_conn = mock_connect.return_value
|
||||
mock_cursor = mock_conn.cursor.return_value
|
||||
# Mock fetchone to return (0,) indicating transaction doesn't exist yet
|
||||
mock_cursor.fetchone.return_value = (0,)
|
||||
|
||||
result = await database_service._persist_transactions_sqlite(
|
||||
"test-account-123", sample_transactions_db_format
|
||||
@@ -338,6 +340,29 @@ class TestDatabaseService:
|
||||
mock_conn.commit.assert_called_once()
|
||||
mock_conn.close.assert_called_once()
|
||||
|
||||
async def test_persist_transactions_sqlite_duplicate_detection(
|
||||
self, database_service, sample_transactions_db_format
|
||||
):
|
||||
"""Test that existing transactions are not returned as new."""
|
||||
with patch("sqlite3.connect") as mock_connect:
|
||||
mock_conn = mock_connect.return_value
|
||||
mock_cursor = mock_conn.cursor.return_value
|
||||
# Mock fetchone to return (1,) indicating transaction already exists
|
||||
mock_cursor.fetchone.return_value = (1,)
|
||||
|
||||
result = await database_service._persist_transactions_sqlite(
|
||||
"test-account-123", sample_transactions_db_format
|
||||
)
|
||||
|
||||
# Should return empty list since all transactions already exist
|
||||
assert len(result) == 0
|
||||
|
||||
# Verify database operations still happened (INSERT OR REPLACE executed)
|
||||
mock_connect.assert_called()
|
||||
mock_cursor.execute.assert_called()
|
||||
mock_conn.commit.assert_called_once()
|
||||
mock_conn.close.assert_called_once()
|
||||
|
||||
async def test_persist_transactions_sqlite_error(self, database_service):
|
||||
"""Test handling error during transaction persistence."""
|
||||
with patch("sqlite3.connect") as mock_connect:
|
||||
|
||||
Reference in New Issue
Block a user