Commit graph

64 commits

Author SHA1 Message Date
43b250e157
small fixes 2025-12-27 12:52:43 +01:00
549fbf4975
Step 8: Cleanup old constants
- Remove EUR_TRADE_MIN, EUR_TRADE_MAX, PREMIUM_PERCENTAGE from shared_constants.py
- Remove eurTradeMin, eurTradeMax, premiumPercentage from shared/constants.json
- Update validate_constants.py to not require removed fields
- Update seed.py and seed_e2e.py to use defaults if fields don't exist
- Update tests to handle missing constants gracefully
2025-12-26 20:27:03 +01:00
41e158376c
Step 6: Update exchange creation logic to use new pricing config
- Update ExchangeService to load pricing config from database
- Update validate_eur_amount to use direction-specific limits
- Update apply_premium_for_direction to calculate base + extra premium
- Update create_exchange to use new premium calculation
- Add tests for premium calculation (small trade extra, large trade base only, direction-specific)
- Update existing tests to account for new premium calculation
2025-12-26 20:24:13 +01:00
d317939ad0
Step 5: Update exchange price endpoint to use new pricing config
- Update ExchangeConfigResponse schema with direction-specific fields
- Remove premium_percentage from PriceResponse (now in config)
- Update price endpoint to load pricing config from database
- Update frontend to use direction-specific min/max and calculate premium
- Update tests to seed pricing config
- Add logic to clamp amount when direction changes
2025-12-26 20:20:23 +01:00
4d0dad8e2b
Step 3: Add admin API endpoints for pricing configuration
- Add PricingConfigResponse and PricingConfigUpdate schemas
- Create PricingService with validation logic
- Add GET and PUT endpoints in routes/pricing.py
- Add MANAGE_PRICING permission to admin role
- Register pricing router in main.py
- Add comprehensive API tests for permissions and validation
2025-12-26 20:13:24 +01:00
74b934135a
Step 2: Add seeding logic for pricing config
- Add seed_pricing_config() function to seed.py
- Seed initial values from shared/constants.json
- Add seeding to seed_e2e.py for E2E tests
- Add tests for seeding functionality
2025-12-26 20:11:00 +01:00
32ce27180d
Step 1: Add PricingConfig model and PricingRepository
- Create PricingConfig model with all required fields (premium settings, trade limits)
- Implement PricingRepository with singleton pattern (get_current, create_or_update)
- Add comprehensive tests for repository functionality
- Export model and repository in __init__.py files
2025-12-26 20:08:35 +01:00
280c1e5687
Move slot expansion logic to ExchangeService
- Add get_available_slots() and _expand_availability_to_slots() to ExchangeService
- Update routes/exchange.py to use ExchangeService.get_available_slots()
- Remove all business logic from get_available_slots endpoint
- Add AvailabilityRepository to ExchangeService dependencies
- Add Availability and BookableSlot imports to ExchangeService
- Fix import path for validate_date_in_range (use date_validation module)
- Remove unused user_repo variable and import from routes/invites.py
- Fix mypy error in ValidationError by adding proper type annotation
2025-12-25 18:42:46 +01:00
badb45da59
Extract price logic to PriceService
- Create PriceService with get_recent_prices() and fetch_and_store_price()
- Update routes/audit.py to use PriceService instead of direct queries
- Use PriceHistoryMapper consistently
- Update test to patch services.price.fetch_btc_eur_price
2025-12-25 18:30:26 +01:00
139a5fbef3
parallel tests 2025-12-25 00:48:22 +01:00
73a45b81cc
fast back 2025-12-25 00:33:05 +01:00
4be45f8f7c
lots of stuff 2025-12-23 17:03:51 +01:00
43a58565c0
Fix test to use different dates for multiple trades 2025-12-23 15:57:43 +01:00
0c75583930
Add endpoint to get a single trade by ID 2025-12-23 15:52:02 +01:00
04192799ab
Add validation to prevent booking two trades on the same day 2025-12-23 15:50:14 +01:00
8936d802a6
Add Lightning amount threshold validation 2025-12-23 14:46:03 +01:00
28e8ba218f
Update create_exchange endpoint to accept and validate bitcoin_transfer_method 2025-12-23 14:40:42 +01:00
e1c7c5209f
Add bitcoin_transfer_method field to Exchange model with default value 2025-12-23 14:34:22 +01:00
2efbd2c665
fix: derive valid slot minutes from SLOT_DURATION_MINUTES constant
Replace hardcoded (0, 15, 30, 45) tuple with computed range based on
the SLOT_DURATION_MINUTES constant. This ensures the validation stays
in sync if the slot duration is ever changed.

Add test to verify slot minute boundary validation.
2025-12-23 12:17:40 +01:00
ca3a08a236
test: improve e2e tests and add COMPLETE_EXCHANGE permission tests
- Fix E2E test assertion for buy/sell direction change
- Add data-testid to date buttons for reliable e2e selection
- Update e2e tests to use data-testid instead of fragile weekday matching
- Add tests for regular user cannot complete/no-show trades (COMPLETE_EXCHANGE permission)
2025-12-23 11:00:32 +01:00
ef01a970d5
feat: add /api/admin/users/search endpoint
- Add endpoint to search users by email (case-insensitive)
- Limit results to 10 for autocomplete purposes
- Require VIEW_ALL_EXCHANGES permission (admin only)
- Add tests for search functionality and access control
2025-12-23 10:55:44 +01:00
ce8f5a1183
test: Add test for cancelled slot becoming available again
Verifies that when a user cancels their trade, the slot becomes
available for booking by other users.
2025-12-23 10:41:08 +01:00
29b0438416
fix: Prevent user from cancelling trades after slot time has passed
Users can no longer cancel trades once the slot time has passed.
Added test to verify this behavior.
2025-12-23 10:39:09 +01:00
bf57fc6b77
fix: Remove agreed_price from price API response
The agreed_price depends on trade direction (buy/sell) and must be
calculated on the frontend. Returning a buy-side-only agreed_price
from the API was misleading and unused.

Frontend already calculates the direction-aware price correctly.
2025-12-23 10:36:18 +01:00
743129b11d
Fix: Update test_permissions.py to use new exchange permissions 2025-12-22 20:23:41 +01:00
edc292986f
Fix: Delete deprecated test_booking.py 2025-12-22 20:23:09 +01:00
811fdf2663
Phase 2.5: Add exchange endpoint tests
Comprehensive test coverage for exchange endpoints:
- Price endpoint: permission checks, price retrieval, staleness, config
- Create exchange: buy/sell, double booking, validation, stale price
- User trades: list trades, cancel own trade, cancel restrictions
- Admin trades: view upcoming/past, complete, no-show, cancel

Tests mock the Bitfinex price fetcher to ensure deterministic results.
2025-12-22 18:48:23 +01:00
5bad1e7e17
Phase 0.1: Remove backend deprecated code
- Delete routes: counter.py, sum.py
- Delete jobs.py and worker.py
- Delete tests: test_counter.py, test_jobs.py
- Update audit.py: keep only price-history endpoints
- Update models.py: remove VIEW_COUNTER, INCREMENT_COUNTER, USE_SUM permissions
- Update models.py: remove Counter, SumRecord, CounterRecord, RandomNumberOutcome models
- Update schemas.py: remove sum/counter related schemas
- Update main.py: remove deleted router imports
- Update test_permissions.py: remove tests for deprecated features
- Update test_price_history.py: remove worker-related tests
- Update conftest.py: remove mock_enqueue_job fixture
- Update auth.py: fix example in docstring
2025-12-22 18:07:14 +01:00
3806361fac
feat: add FETCH_PRICE permission for manual price fetch endpoint
The POST /api/audit/price-history/fetch endpoint now requires
FETCH_PRICE permission instead of VIEW_AUDIT, which is more
semantically correct since it's a write operation.
2025-12-22 16:22:54 +01:00
54709888e1
refactor: extract httpx mock helpers in price history tests
- create_mock_httpx_client() for mocking AsyncClient with various configs
- create_bitfinex_ticker_response() for creating ticker response arrays

Reduces test boilerplate significantly.
2025-12-22 16:21:18 +01:00
3abc7b18c6
test: add test for network errors (httpx.ConnectError)
The docstring of fetch_btc_eur_price mentions it raises httpx.RequestError
on network errors, but this wasn't tested. Add test for ConnectError.
2025-12-22 16:11:00 +01:00
a5488fd20b
fix: handle unique constraint violation in manual fetch endpoint
When a duplicate timestamp occurs (rare but possible), return the
existing record instead of failing with a 500 error. This matches
the worker's ON CONFLICT DO NOTHING behavior.

Added test for duplicate timestamp handling.
2025-12-22 16:09:05 +01:00
ec835a2935
refactor: extract 'bitfinex' and 'BTC/EUR' magic strings to constants
Add SOURCE_BITFINEX and PAIR_BTC_EUR constants in price_fetcher.py and
use them consistently in routes/audit.py, worker.py, and tests.
2025-12-22 16:06:56 +01:00
9db43c474e
test: add unit tests for scheduled Bitcoin price job handler 2025-12-22 15:53:05 +01:00
94497f9200
test: add unit tests for price history feature 2025-12-22 15:47:20 +01:00
21698203fe
refactor(auth): unify authorization patterns with MANAGE_OWN_PROFILE permission
Issue #2: The profile route used a custom role-based check instead
of the permission-based pattern used everywhere else.

Changes:
- Add MANAGE_OWN_PROFILE permission to backend Permission enum
- Add permission to ROLE_REGULAR role definition
- Update profile routes to use require_permission(MANAGE_OWN_PROFILE)
- Remove custom require_regular_user dependency
- Update frontend Permission constant and profile page
- Update invites page to use permission instead of role check
- Update profile tests with proper permission mocking

This ensures consistent authorization patterns across all routes.
2025-12-21 23:50:06 +01:00
4d9edd7fd4
refactor: make mock_enqueue_job fixture opt-in instead of autouse
Tests that call POST /api/counter/increment now explicitly request
the mock_enqueue_job fixture. This prevents the mock from masking
issues in other tests that don't need it.
2025-12-21 23:29:48 +01:00
6f3e729b25
refactor: move process_random_number_job import to module level in tests 2025-12-21 23:25:31 +01:00
89fbdb37bd
fix: handle malformed JSON payloads in worker with error logging 2025-12-21 23:24:28 +01:00
b3ed81e8fd
Phase 4: API Endpoint
- Add RandomNumberOutcomeResponse schema to schemas.py
- Add GET /api/audit/random-jobs endpoint to routes/audit.py
- Returns list of outcomes (newest first, no pagination)
- Requires VIEW_AUDIT permission
- Add tests: admin can access, regular user forbidden, unauthenticated 401
2025-12-21 22:53:54 +01:00
7beb213cf5
Phase 3: Outcome storage
- Add RandomNumberOutcome model to models.py
- Update worker.py to execute job logic:
  - Generate random number 0-100
  - Record execution duration
  - Store outcome in database
- Add test_jobs.py with unit tests for job handler logic
2025-12-21 22:50:35 +01:00
6ca0ae88dd
Phase 2: Job enqueueing from counter
- Add backend/jobs.py with enqueue_random_number_job function
- Modify counter increment endpoint to enqueue job after incrementing
- Add mock_enqueue_job fixture to conftest.py for all tests
- Add test_increment_enqueues_job_with_user_id to verify correct user_id
- Job is enqueued synchronously; failure causes request to fail
2025-12-21 22:44:31 +01:00
6c218130e9
Add ruff linter/formatter for Python
- Add ruff as dev dependency
- Configure ruff in pyproject.toml with strict 88-char line limit
- Ignore B008 (FastAPI Depends pattern is standard)
- Allow longer lines in tests for readability
- Fix all lint issues in source files
- Add Makefile targets: lint-backend, format-backend, fix-backend
2025-12-21 21:54:26 +01:00
46c3c2073a
Fix test assertion for updated error message
- Updated test to match new descriptive error message format
- Changed from 'not within available' to 'not within any available time ranges'
- All tests now passing
2025-12-21 18:06:50 +01:00
77e7f98e1e
Fix: Add pagination to admin appointments endpoint
- Added pagination with page/per_page query params
- Fixed N+1 query by using eager-loaded user relationship
- Removed unused _get_user_email helper function
- Updated frontend to handle paginated response
- Regenerated API types
2025-12-21 17:32:25 +01:00
19c313767c
Fix: Validate source_date in copy availability endpoint
Added validation to ensure source_date is within the allowed range
(tomorrow to +30 days) for consistency with target_dates validation.
2025-12-21 17:28:21 +01:00
63cf46c230
Fix: Prevent cancellation of past appointments
Add check to both user and admin cancel endpoints to reject
cancellation of appointments whose slot_start is in the past.
This matches the spec requirement that cancellations can only
happen 'before the appointment'.

Added tests for both user and admin cancel endpoints.

Also includes frontend styling updates.
2025-12-21 17:27:23 +01:00
b3e00b0745
Phase 6: Admin appointments view and cancellation with UI and backend tests 2025-12-21 00:30:09 +01:00
5108a620e7
Phase 5: User appointments view and cancellation with UI and e2e tests 2025-12-21 00:24:16 +01:00
06817875f7
Phase 3: Appointment model & booking API with timezone fix 2025-12-21 00:03:34 +01:00