tigerstar 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tigerstar-0.1.0/.github/workflows/publish.yml +29 -0
- tigerstar-0.1.0/.gitignore +10 -0
- tigerstar-0.1.0/LICENSE +21 -0
- tigerstar-0.1.0/PKG-INFO +113 -0
- tigerstar-0.1.0/README.md +84 -0
- tigerstar-0.1.0/docs/adapters.md +204 -0
- tigerstar-0.1.0/docs/usage.md +377 -0
- tigerstar-0.1.0/example/__init__.py +0 -0
- tigerstar-0.1.0/example/main.py +51 -0
- tigerstar-0.1.0/pyproject.toml +40 -0
- tigerstar-0.1.0/tigerstar/__init__.py +21 -0
- tigerstar-0.1.0/tigerstar/accounts/__init__.py +4 -0
- tigerstar-0.1.0/tigerstar/accounts/model.py +26 -0
- tigerstar-0.1.0/tigerstar/accounts/service.py +34 -0
- tigerstar-0.1.0/tigerstar/core/__init__.py +27 -0
- tigerstar-0.1.0/tigerstar/core/exceptions.py +30 -0
- tigerstar-0.1.0/tigerstar/core/identity.py +22 -0
- tigerstar-0.1.0/tigerstar/core/types.py +37 -0
- tigerstar-0.1.0/tigerstar/engine.py +29 -0
- tigerstar-0.1.0/tigerstar/ledgers/__init__.py +4 -0
- tigerstar-0.1.0/tigerstar/ledgers/model.py +13 -0
- tigerstar-0.1.0/tigerstar/ledgers/service.py +17 -0
- tigerstar-0.1.0/tigerstar/reporting/__init__.py +3 -0
- tigerstar-0.1.0/tigerstar/reporting/service.py +96 -0
- tigerstar-0.1.0/tigerstar/storage/__init__.py +5 -0
- tigerstar-0.1.0/tigerstar/storage/base.py +79 -0
- tigerstar-0.1.0/tigerstar/storage/firestore.py +284 -0
- tigerstar-0.1.0/tigerstar/storage/postgres/001_initial.sql +72 -0
- tigerstar-0.1.0/tigerstar/storage/postgres/__init__.py +4 -0
- tigerstar-0.1.0/tigerstar/storage/postgres/migrations.py +27 -0
- tigerstar-0.1.0/tigerstar/storage/postgres/storage.py +336 -0
- tigerstar-0.1.0/tigerstar/transfers/__init__.py +5 -0
- tigerstar-0.1.0/tigerstar/transfers/model.py +25 -0
- tigerstar-0.1.0/tigerstar/transfers/posting.py +16 -0
- tigerstar-0.1.0/tigerstar/transfers/service.py +187 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.13"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install hatchling build
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
tigerstar-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Eric Kweyunga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
tigerstar-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tigerstar
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Double-entry ledger engine with pluggable storage backends
|
|
5
|
+
Project-URL: Repository, https://github.com/erickweyunga/tigerstar
|
|
6
|
+
Project-URL: Documentation, https://github.com/erickweyunga/tigerstar/tree/main/docs
|
|
7
|
+
Author-email: Eric Kweyunga <maverickweyunga@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: accounting,double-entry,fintech,ledger,payments
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Provides-Extra: all
|
|
20
|
+
Requires-Dist: firebase-admin>=6.0; extra == 'all'
|
|
21
|
+
Requires-Dist: psycopg-pool>=3.1; extra == 'all'
|
|
22
|
+
Requires-Dist: psycopg[binary]>=3.1; extra == 'all'
|
|
23
|
+
Provides-Extra: firestore
|
|
24
|
+
Requires-Dist: firebase-admin>=6.0; extra == 'firestore'
|
|
25
|
+
Provides-Extra: postgres
|
|
26
|
+
Requires-Dist: psycopg-pool>=3.1; extra == 'postgres'
|
|
27
|
+
Requires-Dist: psycopg[binary]>=3.1; extra == 'postgres'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# TigerStar
|
|
31
|
+
|
|
32
|
+
A double-entry ledger engine with pluggable storage backends.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **Double-entry bookkeeping** — every transfer debits one account and credits another
|
|
37
|
+
- **Two-phase transfers** — reserve funds (pending), then post or void
|
|
38
|
+
- **Linked transfers** — atomic chains that all succeed or all fail
|
|
39
|
+
- **Balance constraints** — prevent overdrafts with account flags
|
|
40
|
+
- **Multi-currency** — separate ledgers per currency with configurable precision
|
|
41
|
+
- **Financial reporting** — trial balance, balance sheet, general ledger
|
|
42
|
+
- **Storage adapters** — swap between Firestore and PostgreSQL without changing application code
|
|
43
|
+
- **Concurrent-safe** — row-level locking (Postgres) or optimistic transactions (Firestore)
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install tigerstar[postgres] # PostgreSQL only
|
|
49
|
+
pip install tigerstar[firestore] # Firestore only
|
|
50
|
+
pip install tigerstar[all] # both backends
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### With Firestore
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from tigerstar import TigerStar, FirestoreStorage
|
|
59
|
+
|
|
60
|
+
storage = FirestoreStorage(credentials_path="path/to/firebase-adminsdk.json")
|
|
61
|
+
engine = TigerStar(storage=storage)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### With PostgreSQL
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from tigerstar import TigerStar, PostgresStorage
|
|
68
|
+
|
|
69
|
+
storage = PostgresStorage(dsn="postgresql://user:pass@localhost:5432/dbname")
|
|
70
|
+
storage.migrate()
|
|
71
|
+
engine = TigerStar(storage=storage)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Create a ledger and move money
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from tigerstar import Ledger, Account, AccountType, AccountFlags, Transfer, TransferCode
|
|
78
|
+
|
|
79
|
+
ledger = Ledger(currency="TZS", precision=0, max_transfer_amount=10_000_000)
|
|
80
|
+
engine.create_ledger(ledger)
|
|
81
|
+
|
|
82
|
+
cash = Account(ledger_id=ledger.id, code=AccountType.ASSET)
|
|
83
|
+
user = Account(
|
|
84
|
+
ledger_id=ledger.id,
|
|
85
|
+
code=AccountType.LIABILITY,
|
|
86
|
+
flags=AccountFlags(debits_must_not_exceed_credits=True),
|
|
87
|
+
)
|
|
88
|
+
engine.create_accounts([cash, user])
|
|
89
|
+
|
|
90
|
+
engine.create_transfers([
|
|
91
|
+
Transfer(
|
|
92
|
+
debit_account_id=cash.id,
|
|
93
|
+
credit_account_id=user.id,
|
|
94
|
+
ledger_id=ledger.id,
|
|
95
|
+
amount=50000,
|
|
96
|
+
code=TransferCode.PAYMENT,
|
|
97
|
+
),
|
|
98
|
+
])
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Storage Adapters
|
|
102
|
+
|
|
103
|
+
| Adapter | Database | Best For |
|
|
104
|
+
|---------|----------|----------|
|
|
105
|
+
| `FirestoreStorage` | Google Cloud Firestore | Serverless, zero-ops, auto-scaling |
|
|
106
|
+
| `PostgresStorage` | PostgreSQL | Financial-grade ACID, SQL flexibility, cost control |
|
|
107
|
+
|
|
108
|
+
Both adapters implement the same interface — swap one for the other with zero application changes. See [docs/adapters.md](docs/adapters.md) for connection pooling, migrations, and writing custom adapters.
|
|
109
|
+
|
|
110
|
+
## Documentation
|
|
111
|
+
|
|
112
|
+
- [Usage Guide](docs/usage.md) — ledgers, accounts, transfers, reporting
|
|
113
|
+
- [Storage Adapters](docs/adapters.md) — setup, configuration, custom adapters
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# TigerStar
|
|
2
|
+
|
|
3
|
+
A double-entry ledger engine with pluggable storage backends.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Double-entry bookkeeping** — every transfer debits one account and credits another
|
|
8
|
+
- **Two-phase transfers** — reserve funds (pending), then post or void
|
|
9
|
+
- **Linked transfers** — atomic chains that all succeed or all fail
|
|
10
|
+
- **Balance constraints** — prevent overdrafts with account flags
|
|
11
|
+
- **Multi-currency** — separate ledgers per currency with configurable precision
|
|
12
|
+
- **Financial reporting** — trial balance, balance sheet, general ledger
|
|
13
|
+
- **Storage adapters** — swap between Firestore and PostgreSQL without changing application code
|
|
14
|
+
- **Concurrent-safe** — row-level locking (Postgres) or optimistic transactions (Firestore)
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install tigerstar[postgres] # PostgreSQL only
|
|
20
|
+
pip install tigerstar[firestore] # Firestore only
|
|
21
|
+
pip install tigerstar[all] # both backends
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### With Firestore
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from tigerstar import TigerStar, FirestoreStorage
|
|
30
|
+
|
|
31
|
+
storage = FirestoreStorage(credentials_path="path/to/firebase-adminsdk.json")
|
|
32
|
+
engine = TigerStar(storage=storage)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### With PostgreSQL
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from tigerstar import TigerStar, PostgresStorage
|
|
39
|
+
|
|
40
|
+
storage = PostgresStorage(dsn="postgresql://user:pass@localhost:5432/dbname")
|
|
41
|
+
storage.migrate()
|
|
42
|
+
engine = TigerStar(storage=storage)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Create a ledger and move money
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from tigerstar import Ledger, Account, AccountType, AccountFlags, Transfer, TransferCode
|
|
49
|
+
|
|
50
|
+
ledger = Ledger(currency="TZS", precision=0, max_transfer_amount=10_000_000)
|
|
51
|
+
engine.create_ledger(ledger)
|
|
52
|
+
|
|
53
|
+
cash = Account(ledger_id=ledger.id, code=AccountType.ASSET)
|
|
54
|
+
user = Account(
|
|
55
|
+
ledger_id=ledger.id,
|
|
56
|
+
code=AccountType.LIABILITY,
|
|
57
|
+
flags=AccountFlags(debits_must_not_exceed_credits=True),
|
|
58
|
+
)
|
|
59
|
+
engine.create_accounts([cash, user])
|
|
60
|
+
|
|
61
|
+
engine.create_transfers([
|
|
62
|
+
Transfer(
|
|
63
|
+
debit_account_id=cash.id,
|
|
64
|
+
credit_account_id=user.id,
|
|
65
|
+
ledger_id=ledger.id,
|
|
66
|
+
amount=50000,
|
|
67
|
+
code=TransferCode.PAYMENT,
|
|
68
|
+
),
|
|
69
|
+
])
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Storage Adapters
|
|
73
|
+
|
|
74
|
+
| Adapter | Database | Best For |
|
|
75
|
+
|---------|----------|----------|
|
|
76
|
+
| `FirestoreStorage` | Google Cloud Firestore | Serverless, zero-ops, auto-scaling |
|
|
77
|
+
| `PostgresStorage` | PostgreSQL | Financial-grade ACID, SQL flexibility, cost control |
|
|
78
|
+
|
|
79
|
+
Both adapters implement the same interface — swap one for the other with zero application changes. See [docs/adapters.md](docs/adapters.md) for connection pooling, migrations, and writing custom adapters.
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
- [Usage Guide](docs/usage.md) — ledgers, accounts, transfers, reporting
|
|
84
|
+
- [Storage Adapters](docs/adapters.md) — setup, configuration, custom adapters
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Storage Adapters
|
|
2
|
+
|
|
3
|
+
TigerStar uses a storage adapter pattern. The engine doesn't care which database you use — swap the adapter and everything works the same.
|
|
4
|
+
|
|
5
|
+
## Available Adapters
|
|
6
|
+
|
|
7
|
+
| Adapter | Database | Best For |
|
|
8
|
+
|---------|----------|----------|
|
|
9
|
+
| `FirestoreStorage` | Google Cloud Firestore | Serverless, zero-ops, auto-scaling |
|
|
10
|
+
| `PostgresStorage` | PostgreSQL | Financial-grade ACID, SQL flexibility, cost control |
|
|
11
|
+
|
|
12
|
+
## Firestore Adapter
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from tigerstar import TigerStar, FirestoreStorage
|
|
16
|
+
|
|
17
|
+
storage = FirestoreStorage(
|
|
18
|
+
credentials_path="path/to/firebase-adminsdk.json",
|
|
19
|
+
database_id="default", # optional, defaults to "default"
|
|
20
|
+
)
|
|
21
|
+
engine = TigerStar(storage=storage)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Requirements
|
|
25
|
+
|
|
26
|
+
- `firebase-admin` package
|
|
27
|
+
- A Firebase project with Firestore enabled
|
|
28
|
+
- Service account JSON credentials
|
|
29
|
+
|
|
30
|
+
### Collections Created
|
|
31
|
+
|
|
32
|
+
- `ledgers`
|
|
33
|
+
- `accounts`
|
|
34
|
+
- `transfers`
|
|
35
|
+
- `postings`
|
|
36
|
+
|
|
37
|
+
### Notes
|
|
38
|
+
|
|
39
|
+
- Transactions use Firestore's built-in optimistic concurrency
|
|
40
|
+
- All reads happen before writes within a transaction
|
|
41
|
+
- Scales automatically — no infrastructure to manage
|
|
42
|
+
- Pay per read/write operation
|
|
43
|
+
|
|
44
|
+
## PostgreSQL Adapter
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from tigerstar import TigerStar, PostgresStorage
|
|
48
|
+
|
|
49
|
+
storage = PostgresStorage(
|
|
50
|
+
dsn="postgresql://user:password@localhost:5432/dbname",
|
|
51
|
+
min_size=5, # minimum pool connections
|
|
52
|
+
max_size=20, # maximum pool connections
|
|
53
|
+
)
|
|
54
|
+
storage.migrate() # create tables on first run
|
|
55
|
+
engine = TigerStar(storage=storage)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Requirements
|
|
59
|
+
|
|
60
|
+
- `psycopg[binary]` and `psycopg-pool` packages
|
|
61
|
+
- PostgreSQL 15+ (recommended: 17+)
|
|
62
|
+
|
|
63
|
+
### Connection Pooling
|
|
64
|
+
|
|
65
|
+
The adapter uses `psycopg_pool.ConnectionPool` internally. Connections are reused across requests — no per-operation connection overhead.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Custom pool sizing for high-throughput
|
|
69
|
+
storage = PostgresStorage(
|
|
70
|
+
dsn="postgresql://user:pass@localhost/otta",
|
|
71
|
+
min_size=10, # keep 10 connections warm
|
|
72
|
+
max_size=50, # burst up to 50 under load
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For production with multiple app instances, put PgBouncer in front of PostgreSQL:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Point at PgBouncer (transaction pooling mode)
|
|
80
|
+
storage = PostgresStorage(
|
|
81
|
+
dsn="postgresql://user:pass@localhost:6432/otta",
|
|
82
|
+
min_size=5,
|
|
83
|
+
max_size=20,
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Migrations
|
|
88
|
+
|
|
89
|
+
Tables are created via SQL migration files in `src/storage/postgres/`.
|
|
90
|
+
|
|
91
|
+
**Option 1 — via the storage instance:**
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
storage = PostgresStorage(dsn="postgresql://...")
|
|
95
|
+
storage.migrate()
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Option 2 — import and run directly:**
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import psycopg
|
|
102
|
+
from tigerstar.storage.postgres import run_migrations
|
|
103
|
+
|
|
104
|
+
conn = psycopg.connect("postgresql://user:pass@localhost/otta", autocommit=True)
|
|
105
|
+
run_migrations(conn)
|
|
106
|
+
conn.close()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Migrations are versioned. Each `.sql` file runs once — tracked in a `schema_migrations` table. To add a new migration, create a new file like `002_add_column.sql` in the `src/storage/postgres/` folder.
|
|
110
|
+
|
|
111
|
+
### Concurrency
|
|
112
|
+
|
|
113
|
+
- Uses `SELECT ... FOR UPDATE` with deterministic lock ordering
|
|
114
|
+
- Account IDs are sorted before locking — prevents deadlocks
|
|
115
|
+
- Ledger validation runs outside the transaction to minimize lock hold time
|
|
116
|
+
- Read Committed isolation level (default) + explicit row locks
|
|
117
|
+
|
|
118
|
+
### Schema Constraints
|
|
119
|
+
|
|
120
|
+
The database enforces integrity at the SQL level:
|
|
121
|
+
|
|
122
|
+
- `CHECK (amount > 0)` — no zero or negative transfers
|
|
123
|
+
- `CHECK (debit_account_id != credit_account_id)` — can't transfer to self
|
|
124
|
+
- `CHECK (debits_pending >= 0 ...)` — balances never go negative
|
|
125
|
+
- Foreign keys on all references
|
|
126
|
+
|
|
127
|
+
### Indexes
|
|
128
|
+
|
|
129
|
+
Optimized for ledger workloads:
|
|
130
|
+
|
|
131
|
+
- Covering index on `transfers(ledger_id, created_at)` — avoids heap lookups
|
|
132
|
+
- Partial index on pending transfers — fast timeout queries
|
|
133
|
+
- Composite index on `postings(account_id, created_at)` — fast general ledger queries
|
|
134
|
+
|
|
135
|
+
## Writing a Custom Adapter
|
|
136
|
+
|
|
137
|
+
Implement `StorageBase`:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from tigerstar.storage.base import StorageBase
|
|
141
|
+
|
|
142
|
+
class MyStorage(StorageBase):
|
|
143
|
+
|
|
144
|
+
def save_ledger(self, ledger):
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
def get_ledger(self, ledger_id):
|
|
148
|
+
...
|
|
149
|
+
|
|
150
|
+
def save_account(self, account):
|
|
151
|
+
...
|
|
152
|
+
|
|
153
|
+
def save_accounts_batch(self, accounts):
|
|
154
|
+
...
|
|
155
|
+
|
|
156
|
+
def get_account(self, account_id):
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
def get_accounts_batch(self, account_ids):
|
|
160
|
+
...
|
|
161
|
+
|
|
162
|
+
def save_transfer(self, transfer):
|
|
163
|
+
...
|
|
164
|
+
|
|
165
|
+
def get_transfer(self, transfer_id):
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
def save_posting(self, posting):
|
|
169
|
+
...
|
|
170
|
+
|
|
171
|
+
def get_postings_for_transfer(self, transfer_id):
|
|
172
|
+
...
|
|
173
|
+
|
|
174
|
+
def execute_transfer(self, transfers, account_ids, pending_ids, process):
|
|
175
|
+
"""
|
|
176
|
+
Must be atomic. Steps:
|
|
177
|
+
1. Read pending transfers by pending_ids (if any)
|
|
178
|
+
2. Read and lock accounts by account_ids
|
|
179
|
+
3. Call process(accounts, pending_transfers) -> (results, updated_accounts, postings)
|
|
180
|
+
4. Write updated accounts, new transfers, and postings
|
|
181
|
+
5. Return results
|
|
182
|
+
All within a single transaction.
|
|
183
|
+
"""
|
|
184
|
+
...
|
|
185
|
+
|
|
186
|
+
def query_accounts_by_ledger(self, ledger_id):
|
|
187
|
+
...
|
|
188
|
+
|
|
189
|
+
def query_transfers_by_ledger(self, ledger_id):
|
|
190
|
+
...
|
|
191
|
+
|
|
192
|
+
def query_postings_by_account(self, account_id):
|
|
193
|
+
...
|
|
194
|
+
|
|
195
|
+
def query_postings_all(self):
|
|
196
|
+
...
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Then use it:
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
storage = MyStorage(...)
|
|
203
|
+
engine = TigerStar(storage=storage)
|
|
204
|
+
```
|