Commit graph

29 commits

Author SHA1 Message Date
7c4959946b
supply-chain: hash-pin prod dependencies (requirements-prod.lock)
Prod previously installed via 'pip install .' (reads unbounded requirements.py3.txt)
plus 'pip install --upgrade -r requirements-prod.txt' — every deploy re-resolved to
whatever PyPI served, unverified. A poisoned release of any dep (stripe, boto3,
sqlalchemy, pyramid...) would land in a payment app.

- requirements-prod.in: source (runtime + prod-server deps)
- requirements-prod.lock: 68 pkgs pinned to exact versions + SHA256 (854 hashes),
  generated with uv pip compile --generate-hashes
- install-source-prod now: pip install --require-hashes -r requirements-prod.lock
  then pip install --no-deps . — no floating resolve at deploy time
- make pins-lock regenerates the lock deliberately

Validated locally: lock installs under --require-hashes, app imports, 791 logic
tests pass under resolved versions (functional tests need MPS_TEST_* env, gated in CI).
2026-05-21 08:55:33 -04:00
dc06551967 docs: use make migration — never hand-write revision IDs 2026-04-06 14:20:13 -04:00
c60c6bd84b Pin setuptools<81 — version 82 removed pkg_resources
Pyramid 2.0.2 imports pkg_resources which was dropped from setuptools 81+.
Pin to <81 until Pyramid removes its pkg_resources dependency.
2026-02-08 12:18:29 -05:00
2bf586595f Install setuptools before editable install in Makefile
Cached CI venvs skip dependency resolution on editable installs.
Explicitly install setuptools first in both dev and prod targets.
2026-02-08 12:11:58 -05:00
af4b70a160 Fix parallel test execution with isolated per-worker databases
The previous parallel test attempt failed because all workers were trying
to use the same SQLite database file, causing locking errors.

Solution:
- Created conftest.py to configure pytest-xdist workers
- Each worker gets a unique database file (test_make_post_sell_gw0.sqlite, etc.)
- Enabled SQLite WAL (Write-Ahead Logging) mode for better concurrency
- WAL allows multiple readers while a writer is active
- Modified test.ini to use $TEST_DATABASE_PATH environment variable
- Automatic cleanup of worker databases after test completion

Benefits:
- True isolation between test workers
- No database locking conflicts
- Tests can run fully in parallel
- Expected test time reduction from 30min to ~5-10min

Each worker's database is completely isolated, preventing the SQLite
"database is locked" errors that plagued the previous attempt.
2026-01-21 12:07:16 -05:00
012014a20c Add parallel test execution with pytest-xdist
The test suite was taking 30 minutes to run sequentially. With 434 tests,
parallel execution should significantly reduce CI time.

Changes:
- Add pytest-xdist to requirements-test.txt
- Update Makefile test target to use 'pytest -n auto'
- Auto mode automatically uses number of CPU cores available

Expected improvements:
- Unit tests and model tests can run fully in parallel
- Integration tests with isolated databases can run in parallel
- Overall test time should reduce to ~5-10 minutes on multi-core CI

Note: Crypto RPC tests may still be a bottleneck if they hit shared
wallet daemons, but most other tests should parallelize well.
2026-01-21 11:57:46 -05:00
3fedfeb849 Update state machine documentation to use dash-separated naming
- Convert all state names from underscore to dash format in markdown documentation
- Ensures consistency across all documentation formats (dot, svg, markdown)
- All payment states now use dashes: confirmed-complete, underpaid-refunded, etc.
- Maintains consistency with the source dot file which is the canonical reference

This completes the documentation naming convention standardization.
2025-10-04 13:02:07 -04:00
619aca286a Implement Stripe disable/enable functionality and improve checkout UX
## Major Features Added:
- **Stripe Disable/Enable**: Added per-shop Stripe enable/disable functionality similar to crypto currencies
- **Shop-themed Link Styling**: Implemented comprehensive link theming system using CSS classes
- **Responsive Checkout Layout**: Simplified checkout page to always use single-column responsive design

## Database Changes:
- Added `stripe_enabled` column to `mps_shop` table (defaults to enabled)
- Created Alembic migration with proper SQLite `server_default="1"` handling

## Template Updates:
- **Shop Settings**: Added Stripe disable/re-enable buttons with proper conditional logic
- **Checkout Page**: Simplified to single-column responsive layout (640px max, mobile-friendly)
- **Link Theming**: Added `shop-theme-link-color` class to all product/shop links across templates
- **Button Consistency**: Standardized all "Update" buttons to "Save" in shop settings

## Code Architecture:
- **Request Methods**: Added `request.stripe_globally_enabled` for clean separation of global vs per-shop settings
- **DRY Refactor**: Made `request.stripe_enabled` use `request.stripe_globally_enabled` to eliminate code duplication
- **CSS Grid Only**: Removed flexbox usage, enforced CSS Grid for all layouts per project standards

## Bug Fixes:
- Fixed "refund pending" messages showing incorrectly for `underpaid-not-refunded` status
- Fixed economically unviable refund emails showing incorrect "no fees deducted" messages
- Fixed checkout page horizontal scrolling issues on mobile/desktop
- Fixed CSS specificity issues with global link styles overriding shop themes

## Documentation:
- **CLAUDE.md**: Added comprehensive database migration guide with SQLite best practices
- **CSS Requirements**: Documented CSS Grid-only layout policy
- **Migration Examples**: Added server_default examples for SQLite column additions

## Templates Modified:
- cart.j2, cart_checkout.j2, shop_settings.j2, crypto_quotes_history.j2
- All template files updated with consistent shop-theme-link-color classes
- Ribbon snippet updated with proper CSS class definitions

This update provides shop owners full control over their Stripe payment acceptance
while maintaining backwards compatibility and improving overall user experience.
2025-10-04 10:41:20 -04:00
d2d09e8851 Fix Dogecoin multi-output refunds with proper fee handling
- Add payment amount to shop output for overpayment refunds
- Both XMR and DOGE now send payment + restocking fee to shop
- Fix insufficient funds error by using conservative fee buffer (0.01 DOGE)
- Round outputs down to 3 decimal places to avoid precision issues
- Update sendmany to try actual account first (where funds are located)
- Add better error handling for different account formats
- Fix fee calculation to properly account for Dogecoin's fee-on-top model

The issue was that sendmany adds network fee on top of outputs, and we
were trying to send exactly the wallet balance, leaving no room for fees.
Now we reserve 0.01 DOGE for fees and round conservatively.
2025-10-02 16:19:23 -04:00
04583ace53 Clean up Makefile sweep commands and documentation
- Remove error messages from sweep/sweep-check Makefile targets
- Keep commands functional for developers/admins in local environments
- Simplify documentation to focus on automatic sweeping behavior
- Maintain separation between end-user docs and dev tools
2025-09-30 20:54:50 -04:00
ed98674c48 Remove untested sweep_to_cold script and references
- Delete make_post_sell/lib/sweep_to_cold.py (untested, risky for production)
- Remove sweep_to_cold console script entry from setup.py
- Update Makefile to deprecate sweep/sweep-check, recommend tested alternatives
- Update CRYPTO.rst documentation to promote sweep-all and sweep-all-doge
- Reduce technical debt by eliminating dangerous untested code path
- Users should use properly tested sweep-all/sweep-all-doge commands instead
2025-09-30 20:54:50 -04:00
6ceb9375de modified: Makefile
new file:   docs/state-machine.dot
	new file:   docs/state-machine.dot.svg
	renamed:    state-machine.svg -> docs/state-machine.svg
2025-09-30 15:43:54 -04:00
7885ed5d76 Fix make serve binding and add missing DogecoinClient methods
- Remove config modification logic from make serve to respect existing listen settings
- Remove --reload flag to test remote host binding
- Add missing listsinceblock method to DogecoinClient and MockDogecoinClient for late payment scanning
- Update Dogecoin auto sweep test expectations to match new 0.002 DOGE fee buffer (was 0.1 DOGE)
2025-09-28 17:17:25 -04:00
27a8109f47 Fix make serve to properly override listen address
Use pserve config override syntax: listen=0.0.0.0:6501
instead of invalid --bind flag. This forces the server to bind
to all interfaces on port 6501 for external access during development.
2025-09-28 17:03:23 -04:00
1d75cfdcc6 Fix make serve to respect 0.0.0.0:6501 bind address
The --reload flag was ignoring the listen = 0.0.0.0:6501 setting
in development.ini. Added explicit --bind=0.0.0.0:6501 to make serve
target to ensure development server binds to all interfaces on port 6501.

This allows external access to the dev server for testing.
2025-09-28 17:01:44 -04:00
3b27bb55ce Add Dogecoin production support: sweep-all-doge and getblockhash method
1. Added getblockhash() method to DogecoinClient for late payment scanning
   - Fixes 'DogecoinClient' object has no attribute 'getblockhash' error
   - Required for crypto watcher to scan for missed payments

2. Added sweep-all-doge Makefile target for dust collection
   - Sweeps ALL spendable Dogecoin balance to cold storage
   - Uses sendtoaddress with subtractfeefromamount=true for complete sweep
   - Includes safety confirmations and balance checks
   - Perfect for cleaning up dust from hot wallet

Usage:
  COLD_WALLET_ADDRESS=DYourColdAddress make sweep-all-doge

Critical for production Dogecoin deployment and hot wallet management.
2025-09-28 16:49:13 -04:00
30a5088ea0 Fix duplicate payment refunds by inheriting user's saved refund address
- Add UserCryptoRefundAddress import and lookup function
- Update _create_duplicate_payment to lookup saved refund address
- Fix refund processing to check saved addresses if not set on payment
- Add test for refund address inheritance
- Add Makefile target for sweeping all wallet funds (sweep-all)

This fixes the issue where duplicate payments weren't being refunded
because they had no refund_address set. Now the system will:
1. First check if original payment has refund_address
2. If not, lookup user's saved refund address for that coin type
3. Use the found address for the duplicate payment record

Also added sweep-all target to collect dust from all accounts.
2025-09-28 08:35:08 -04:00
3f313b6bba Add complete status enums for crypto refunds and fix cancelled payment viewing
- Add terminal -complete status enums for all refund types
- Update crypto watcher to transition refunds to complete status at 10+ confirmations
- Fix cancelled payment quote viewing with proper access control and USD calculation
- Update status mappings and templates to support complete statuses
- Move payment status display to breakdown section in checkout template
- Add View Quote buttons for cancelled and refunded payments

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 22:31:34 -04:00
4fbe9fedd4 Apply black code formatting
Formatted Python code using black for:
- crypto_clients.py
- crypto_watcher.py
- test_crypto_watcher.py

Maintains consistent code style across the codebase.
2025-09-23 10:49:26 -04:00
68d4ccfc25 Dogecoin payment support 2025-09-23 11:17:05 +00:00
f3cd1e7116 Add Monero (XMR) payment support 2025-09-22 01:45:54 +00:00
89f8737a58 Achieve 100% test coverage for Cart model 2025-07-27 17:53:05 +00:00
1162034875 @echo "Deleting tests from source code for production..."
rm -rf make_post_sell/tests

	modified:   Makefile
2025-03-03 17:14:36 -05:00
2746258ddb early optimization is the death by 1,000 cuts.
modified:   .gitlab-ci.yml
	modified:   Makefile
2025-03-03 10:53:17 -05:00
79aa2ddd6c pypi release prep!
modified:   .gitlab-ci.yml
	modified:   Makefile
	modified:   README.rst
	modified:   setup.py
2025-03-02 08:36:51 -05:00
906e4a93e1 remove SMTP server from dev and use console logs instead. 2025-01-10 13:10:37 +00:00
2c78ba4317 shop sales pages
modified:   Makefile
	modified:   development.ini
	modified:   make_post_sell/models/invoice.py
	modified:   make_post_sell/models/shop.py
	modified:   make_post_sell/routes.py
	modified:   make_post_sell/static/css/common.css
	modified:   make_post_sell/templates/actions_view.j2
	new file:   make_post_sell/templates/sales.j2
	new file:   make_post_sell/templates/sales_details.j2
	modified:   make_post_sell/views/cart.py
	new file:   make_post_sell/views/sales.py
2024-12-11 12:03:54 -05:00
00317c85ae modified: Makefile 2022-05-25 18:08:20 -04:00
c211df66a8 Time to open the sauce : )
Dead man switch activated. Good luck everyone, I wish you the best.

 - BDFL

	new file:   .gitignore
	new file:   MANIFEST.in
	new file:   Makefile
	new file:   README.rst
	new file:   development.ini
	new file:   journal.rst
	new file:   make_post_sell/__init__.py
	new file:   make_post_sell/config_jinja2.py
	new file:   make_post_sell/lib/__init__.py
	new file:   make_post_sell/lib/mail.py
	new file:   make_post_sell/lib/mail_messages.py
	new file:   make_post_sell/lib/render.py
	new file:   make_post_sell/models/__init__.py
	new file:   make_post_sell/models/cart.py
	new file:   make_post_sell/models/cart_coupon.py
	new file:   make_post_sell/models/coupon.py
	new file:   make_post_sell/models/coupon_redemption.py
	new file:   make_post_sell/models/invoice.py
	new file:   make_post_sell/models/market.py
	new file:   make_post_sell/models/meta.py
	new file:   make_post_sell/models/price.py
	new file:   make_post_sell/models/product.py
	new file:   make_post_sell/models/shop.py
	new file:   make_post_sell/models/shop_search_request.py
	new file:   make_post_sell/models/stripe_user_shop.py
	new file:   make_post_sell/models/user.py
	new file:   make_post_sell/models/user_product.py
	new file:   make_post_sell/models/user_shop.py
	new file:   make_post_sell/request_methods.py
	new file:   make_post_sell/routes.py
	new file:   make_post_sell/scripts/__init__.py
	new file:   make_post_sell/scripts/alembic/README
	new file:   make_post_sell/scripts/alembic/env.py
	new file:   make_post_sell/scripts/alembic/script.py.mako
	new file:   make_post_sell/scripts/alembic/versions/15751f5d7a03_add_active_cart_total_in_cents_to_user_.py
	new file:   make_post_sell/scripts/alembic/versions/24662905655f_create_new_active_shop_id_column_on_.py
	new file:   make_post_sell/scripts/alembic/versions/3e1e70bfe89d_google_analytics_id.py
	new file:   make_post_sell/scripts/alembic/versions/4d9da43b0e86_product_visibility_column.py
	new file:   make_post_sell/scripts/alembic/versions/5c40dfb56179_shop_ribbon_columns.py
	new file:   make_post_sell/scripts/alembic/versions/6da97f2f913f_add_updated_timestamp_to_cart.py
	new file:   make_post_sell/scripts/alembic/versions/96f851cbab01_terms_and_privacy.py
	new file:   make_post_sell/scripts/alembic/versions/ab7338eaedf1_add_price_in_cents_column.py
	new file:   make_post_sell/scripts/alembic/versions/af28cc35ed6f_product_bundles.py
	new file:   make_post_sell/scripts/alembic/versions/b0d5604d9255_add_active_cart_count_to_user_table.py
	new file:   make_post_sell/scripts/alembic/versions/bfc4195a7f56_product_is_sellable_coluumn.py
	new file:   make_post_sell/scripts/alembic/versions/c4d5566ec87d_coupon_stackable_and_couponredemption.py
	new file:   make_post_sell/scripts/alembic/versions/e12bbe39d87e_cart_coupon_table.py
	new file:   make_post_sell/scripts/alembic/versions/eadd0d69e133_shop_ribbon_text_color.py
	new file:   make_post_sell/scripts/alembic/versions/f3aa57777025_coupon_table.py
	new file:   make_post_sell/scripts/alembic/versions/f882f2255cd1_add_stripe_secret_and_public_key_to_shop.py
	new file:   make_post_sell/scripts/alembic/versions/fd9f7e2f2b78_user_full_name.py
	new file:   make_post_sell/scripts/initialize_db.py
	new file:   make_post_sell/scripts/pshell.py
	new file:   make_post_sell/static/css/alerts.css
	new file:   make_post_sell/static/css/common.css
	new file:   make_post_sell/static/css/lib.css
	new file:   make_post_sell/static/css/mps.css
	new file:   make_post_sell/static/favicon.ico
	new file:   make_post_sell/static/js/custom.js
	new file:   make_post_sell/static/js/jquery-3.4.1.min.js
	new file:   make_post_sell/static/js/jquery.min.js
	new file:   make_post_sell/static/makepostsell-3.png
	new file:   make_post_sell/static/makepostsell.png
	new file:   make_post_sell/static/mps.png
	new file:   make_post_sell/templates/actions_new.j2
	new file:   make_post_sell/templates/actions_view.j2
	new file:   make_post_sell/templates/base.j2
	new file:   make_post_sell/templates/billing.j2
	new file:   make_post_sell/templates/cart.j2
	new file:   make_post_sell/templates/cart_checkout.j2
	new file:   make_post_sell/templates/carts.j2
	new file:   make_post_sell/templates/content.j2
	new file:   make_post_sell/templates/content_new.j2
	new file:   make_post_sell/templates/coupon.j2
	new file:   make_post_sell/templates/coupon_new.j2
	new file:   make_post_sell/templates/coupons.j2
	new file:   make_post_sell/templates/home.j2
	new file:   make_post_sell/templates/join-or-log-in.j2
	new file:   make_post_sell/templates/markup_editor.j2
	new file:   make_post_sell/templates/markup_renderer.j2
	new file:   make_post_sell/templates/product.j2
	new file:   make_post_sell/templates/product_edit.j2
	new file:   make_post_sell/templates/product_new.j2
	new file:   make_post_sell/templates/products.j2
	new file:   make_post_sell/templates/shop.j2
	new file:   make_post_sell/templates/shop_about.j2
	new file:   make_post_sell/templates/shop_new.j2
	new file:   make_post_sell/templates/shop_products.j2
	new file:   make_post_sell/templates/shop_settings.j2
	new file:   make_post_sell/templates/shops.j2
	new file:   make_post_sell/templates/snippets/csrf.j2
	new file:   make_post_sell/templates/snippets/flash-alerts.j2
	new file:   make_post_sell/templates/snippets/google-analytics.j2
	new file:   make_post_sell/templates/snippets/optional-javascript.j2
	new file:   make_post_sell/templates/snippets/ribbon.j2
	new file:   make_post_sell/templates/snippets/search.j2
	new file:   make_post_sell/templates/snippets/stripe.j2
	new file:   make_post_sell/templates/update-card.j2
	new file:   make_post_sell/templates/user_settings.j2
	new file:   make_post_sell/tests/__init__.py
	new file:   make_post_sell/tests/test_functional.py
	new file:   make_post_sell/tests/test_models.py
	new file:   make_post_sell/views/__init__.py
	new file:   make_post_sell/views/actions.py
	new file:   make_post_sell/views/authentication.py
	new file:   make_post_sell/views/billing.py
	new file:   make_post_sell/views/cart.py
	new file:   make_post_sell/views/content.py
	new file:   make_post_sell/views/coupon.py
	new file:   make_post_sell/views/misc.py
	new file:   make_post_sell/views/product.py
	new file:   make_post_sell/views/shop.py
	new file:   make_post_sell/views/user.py
	new file:   pytest.ini
	new file:   requirements-dev.txt
	new file:   requirements-prod.txt
	new file:   requirements-test.txt
	new file:   requirements.py3.txt
	new file:   requirements.txt
	new file:   setup.py
	new file:   test.ini
2021-12-31 21:39:40 -05:00