The serializers.py file had two issues:
1. A second definition of TransactionSerializer that included a
non-existent 'price_per_share' field, overriding the correct one
and causing 500 errors on GET/POST /api/invest/transactions/.
2. Duplicate AIHoldingInputSerializer and AIUpdateSerializer blocks
that were redundant (same content as the first definitions).
Removed all duplicate class definitions, leaving only the correct
single definitions that match the Transaction model fields.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Portfolio management (MOMO, IBKR personal, IBKR Yanhua)
- Stock holdings with transaction history (buy/sell)
- Weekly AI report generation
- Real-time price cache via Finnhub API
- Dashboard with tree view and performance charts
- REST API with AI-friendly batch update endpoint
- Management command for scheduled report generation
For大哥's personal investment advisor system.
- Rewrite nginxmon/geo.py to use maxminddb + DB-IP City Lite MMDB
(https://cdn.jsdelivr.net/npm/dbip-city-lite/dbip-city-lite.mmdb.gz)
instead of ip-api.com HTTP API — eliminates all network timeouts and
rate-limit issues; lookups are now sub-millisecond in-process
- Keep _lookup_batch() signature unchanged so routermon receiver
requires no changes
- MMDB downloaded on first use (lazy) and refreshed monthly via
APScheduler; reader cached module-level (thread-safe for reads)
- Add management command: manage.py download_geo_db
- Update k8s init container to download MMDB on first deploy if absent
- Add maxminddb==3.1.1 dependency
CC BY 4.0 — DB-IP (https://db-ip.com)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stop sending further API requests mid-batch once the backoff is
triggered, saving remaining missing IPs as empty placeholders
immediately instead of waiting for them to timeout one-by-one.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After _GEO_MISS_THRESHOLD (2) consecutive large all-empty API responses,
assume ip-api.com is unreachable and enter a 5-minute backoff.
During backoff all missing IPs are immediately saved as empty IPGeoCache
placeholders so they are not re-queued. Resets automatically when the
backoff expires and any result is returned.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>