velocity-python 0.0.232__tar.gz → 0.0.234__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.
- {velocity_python-0.0.232/src/velocity_python.egg-info → velocity_python-0.0.234}/PKG-INFO +1 -1
- {velocity_python-0.0.232 → velocity_python-0.0.234}/pyproject.toml +1 -1
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/__init__.py +1 -1
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/__init__.py +8 -0
- velocity_python-0.0.234/src/velocity/payment/charge_rules.py +39 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/demo_profiles.py +78 -29
- {velocity_python-0.0.232 → velocity_python-0.0.234/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/SOURCES.txt +1 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/LICENSE +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/README.md +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/setup.cfg +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/invoices.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/orders.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/payments.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/purchase_orders.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/tests/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/tests/test_email_processing.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/logging.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/authorizenet_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/profiles.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/router.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_decorators.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_payment_demo_profiles.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_payment_profiles.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_payment_router.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_table_alter.py +0 -0
- {velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_where_clause_validation.py +0 -0
|
@@ -55,6 +55,11 @@ from .profiles import (
|
|
|
55
55
|
upsert_payment_profile,
|
|
56
56
|
)
|
|
57
57
|
from .demo_profiles import resolve_demo_charge_cards, get_card_lookup_id
|
|
58
|
+
from .charge_rules import (
|
|
59
|
+
should_charge_immediately,
|
|
60
|
+
is_below_immediate_charge_minimum,
|
|
61
|
+
is_above_immediate_charge_maximum,
|
|
62
|
+
)
|
|
58
63
|
|
|
59
64
|
__all__ = [
|
|
60
65
|
# Base classes
|
|
@@ -83,6 +88,9 @@ __all__ = [
|
|
|
83
88
|
"upsert_payment_profile",
|
|
84
89
|
"resolve_demo_charge_cards",
|
|
85
90
|
"get_card_lookup_id",
|
|
91
|
+
"should_charge_immediately",
|
|
92
|
+
"is_below_immediate_charge_minimum",
|
|
93
|
+
"is_above_immediate_charge_maximum",
|
|
86
94
|
]
|
|
87
95
|
|
|
88
96
|
__version__ = "1.0.0"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Shared immediate-charge validation helpers for payment flows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def should_charge_immediately(total_charge_amount: Any) -> bool:
|
|
9
|
+
"""Return True when an immediate payment should be submitted to a processor."""
|
|
10
|
+
if total_charge_amount in (None, ""):
|
|
11
|
+
return False
|
|
12
|
+
try:
|
|
13
|
+
return float(total_charge_amount) > 0
|
|
14
|
+
except (TypeError, ValueError):
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def is_below_immediate_charge_minimum(
|
|
19
|
+
total_charge_amount: Any, minimum_donation_amount: Any
|
|
20
|
+
) -> bool:
|
|
21
|
+
"""Return True only when an actual immediate charge exists and is below the minimum."""
|
|
22
|
+
if not should_charge_immediately(total_charge_amount):
|
|
23
|
+
return False
|
|
24
|
+
try:
|
|
25
|
+
return float(total_charge_amount) < float(minimum_donation_amount)
|
|
26
|
+
except (TypeError, ValueError):
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_above_immediate_charge_maximum(
|
|
31
|
+
total_charge_amount: Any, maximum_donation_amount: Any
|
|
32
|
+
) -> bool:
|
|
33
|
+
"""Return True only when an actual immediate charge exists and is above the maximum."""
|
|
34
|
+
if not should_charge_immediately(total_charge_amount):
|
|
35
|
+
return False
|
|
36
|
+
try:
|
|
37
|
+
return float(total_charge_amount) > float(maximum_donation_amount)
|
|
38
|
+
except (TypeError, ValueError):
|
|
39
|
+
return False
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
"""Demo-only payment profile helpers for charging copied production users safely."""
|
|
2
2
|
|
|
3
|
+
import hashlib
|
|
3
4
|
import os
|
|
4
5
|
from typing import Dict, List, Optional
|
|
5
6
|
|
|
6
7
|
from .profiles import get_payment_profile_sources, upsert_payment_profile
|
|
7
8
|
from .router import get_processor_config
|
|
8
9
|
|
|
9
|
-
_DEMO_BRAINTREE_NONCE = "fake-valid-nonce"
|
|
10
10
|
_DEMO_STRIPE_TOKEN = "tok_visa"
|
|
11
11
|
_DEMO_AUTHORIZE_CARD_NUMBER = "4111111111111111"
|
|
12
12
|
_DEMO_AUTHORIZE_EXPIRATION = "2030-12"
|
|
13
13
|
_DEMO_AUTHORIZE_CARD_CODE = "123"
|
|
14
|
+
_DEMO_BRAINTREE_CARD_NUMBERS = [
|
|
15
|
+
"4111111111111111",
|
|
16
|
+
"4012888888881881",
|
|
17
|
+
"5555555555554444",
|
|
18
|
+
"6011000991300009",
|
|
19
|
+
"378282246310005",
|
|
20
|
+
]
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
def is_demo_environment() -> bool:
|
|
@@ -39,9 +46,42 @@ def _save_payment_profile(tx, data: Dict) -> Dict:
|
|
|
39
46
|
return data
|
|
40
47
|
|
|
41
48
|
|
|
49
|
+
def _stable_hash(value: str) -> int:
|
|
50
|
+
return int(hashlib.sha256(str(value).encode("utf-8")).hexdigest(), 16)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _build_demo_braintree_card_spec(email_address: str) -> Dict[str, str]:
|
|
54
|
+
digest = _stable_hash(email_address)
|
|
55
|
+
card_number = _DEMO_BRAINTREE_CARD_NUMBERS[digest % len(_DEMO_BRAINTREE_CARD_NUMBERS)]
|
|
56
|
+
expiration_month = (digest % 12) + 1
|
|
57
|
+
expiration_year = 2027 + ((digest // len(_DEMO_BRAINTREE_CARD_NUMBERS)) % 3)
|
|
58
|
+
postal_code = f"{10000 + (digest % 89999):05d}"
|
|
59
|
+
return {
|
|
60
|
+
"number": card_number,
|
|
61
|
+
"expiration_date": f"{expiration_month:02d}/{expiration_year}",
|
|
62
|
+
"last4": card_number[-4:],
|
|
63
|
+
"expiration_month": f"{expiration_month:02d}",
|
|
64
|
+
"expiration_year": str(expiration_year),
|
|
65
|
+
"postal_code": postal_code,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _find_matching_braintree_payment_method(customer, card_spec: Dict[str, str]):
|
|
70
|
+
for payment_method in customer.payment_methods:
|
|
71
|
+
if getattr(payment_method, "last_4", None) != card_spec["last4"]:
|
|
72
|
+
continue
|
|
73
|
+
if str(getattr(payment_method, "expiration_month", "")).zfill(2) != card_spec["expiration_month"]:
|
|
74
|
+
continue
|
|
75
|
+
if str(getattr(payment_method, "expiration_year", "")) != card_spec["expiration_year"]:
|
|
76
|
+
continue
|
|
77
|
+
return payment_method
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
42
81
|
def get_card_lookup_id(card: Dict) -> str:
|
|
43
82
|
return str(
|
|
44
|
-
card.get("
|
|
83
|
+
card.get("lookup_id")
|
|
84
|
+
or card.get("sys_id")
|
|
45
85
|
or card.get("payment_profile_id")
|
|
46
86
|
or card.get("customer_profile_id")
|
|
47
87
|
or card.get("src")
|
|
@@ -68,31 +108,35 @@ def _get_demo_braintree_card(tx, user: Dict) -> Dict:
|
|
|
68
108
|
)
|
|
69
109
|
|
|
70
110
|
demo_email = build_demo_profile_email(user["email_address"], "bt")
|
|
111
|
+
card_spec = _build_demo_braintree_card_spec(user["email_address"])
|
|
71
112
|
customer = None
|
|
72
113
|
|
|
73
114
|
collection = gateway.customer.search(braintree.CustomerSearch.email == demo_email)
|
|
74
115
|
for existing_customer in collection.items:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
116
|
+
customer = existing_customer
|
|
117
|
+
payment_method = _find_matching_braintree_payment_method(
|
|
118
|
+
existing_customer, card_spec
|
|
119
|
+
)
|
|
120
|
+
if payment_method:
|
|
121
|
+
return _save_payment_profile(
|
|
122
|
+
tx,
|
|
123
|
+
{
|
|
124
|
+
"src": "BT",
|
|
125
|
+
"card_type": getattr(payment_method, "card_type", "Visa"),
|
|
126
|
+
"card_number": getattr(payment_method, "last_4", card_spec["last4"]),
|
|
127
|
+
"expiration_date": _format_expiration_date(
|
|
128
|
+
getattr(payment_method, "expiration_year", card_spec["expiration_year"]),
|
|
129
|
+
getattr(payment_method, "expiration_month", card_spec["expiration_month"]),
|
|
130
|
+
),
|
|
131
|
+
"payment_profile_id": payment_method.token,
|
|
132
|
+
"customer_profile_id": payment_method.customer_id,
|
|
133
|
+
"email_address": user["email_address"],
|
|
134
|
+
"first_name": user.get("first_name")
|
|
135
|
+
or user["email_address"].split("@")[0],
|
|
136
|
+
"last_name": user.get("last_name") or "Demo",
|
|
137
|
+
"is_default": getattr(payment_method, "default", True),
|
|
138
|
+
},
|
|
139
|
+
)
|
|
96
140
|
|
|
97
141
|
if customer is None:
|
|
98
142
|
result = gateway.customer.create(
|
|
@@ -107,26 +151,29 @@ def _get_demo_braintree_card(tx, user: Dict) -> Dict:
|
|
|
107
151
|
raise RuntimeError(result.message)
|
|
108
152
|
customer = result.customer
|
|
109
153
|
|
|
110
|
-
payment_method_result = gateway.
|
|
154
|
+
payment_method_result = gateway.credit_card.create(
|
|
111
155
|
{
|
|
112
156
|
"customer_id": customer.id,
|
|
113
|
-
"
|
|
157
|
+
"number": card_spec["number"],
|
|
158
|
+
"expiration_date": card_spec["expiration_date"],
|
|
159
|
+
"cvv": "123",
|
|
160
|
+
"billing_address": {"postal_code": card_spec["postal_code"]},
|
|
114
161
|
"options": {"make_default": True, "verify_card": True},
|
|
115
162
|
}
|
|
116
163
|
)
|
|
117
164
|
if not payment_method_result.is_success:
|
|
118
165
|
raise RuntimeError(payment_method_result.message)
|
|
119
166
|
|
|
120
|
-
payment_method = payment_method_result.
|
|
167
|
+
payment_method = payment_method_result.credit_card
|
|
121
168
|
return _save_payment_profile(
|
|
122
169
|
tx,
|
|
123
170
|
{
|
|
124
171
|
"src": "BT",
|
|
125
172
|
"card_type": getattr(payment_method, "card_type", "Visa"),
|
|
126
|
-
"card_number": getattr(payment_method, "last_4", "
|
|
173
|
+
"card_number": getattr(payment_method, "last_4", card_spec["last4"]),
|
|
127
174
|
"expiration_date": _format_expiration_date(
|
|
128
|
-
getattr(payment_method, "expiration_year", "
|
|
129
|
-
getattr(payment_method, "expiration_month", "
|
|
175
|
+
getattr(payment_method, "expiration_year", card_spec["expiration_year"]),
|
|
176
|
+
getattr(payment_method, "expiration_month", card_spec["expiration_month"]),
|
|
130
177
|
),
|
|
131
178
|
"payment_profile_id": payment_method.token,
|
|
132
179
|
"customer_profile_id": customer.id,
|
|
@@ -289,6 +336,7 @@ def resolve_demo_charge_cards(tx, user: Dict, payment_processor: str, cards: Lis
|
|
|
289
336
|
if demo_card:
|
|
290
337
|
merged_card = dict(card)
|
|
291
338
|
merged_card.update(demo_card)
|
|
339
|
+
merged_card["lookup_id"] = demo_card.get("payment_profile_id")
|
|
292
340
|
resolved_cards.append(merged_card)
|
|
293
341
|
else:
|
|
294
342
|
resolved_cards.append(card)
|
|
@@ -299,6 +347,7 @@ def resolve_demo_charge_cards(tx, user: Dict, payment_processor: str, cards: Lis
|
|
|
299
347
|
for source in get_payment_profile_sources(payment_processor):
|
|
300
348
|
demo_card = get_demo_card_for_source(tx, user, source)
|
|
301
349
|
if demo_card:
|
|
350
|
+
demo_card["lookup_id"] = demo_card.get("payment_profile_id")
|
|
302
351
|
return [demo_card]
|
|
303
352
|
|
|
304
353
|
return cards
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/SOURCES.txt
RENAMED
|
@@ -133,6 +133,7 @@ src/velocity/payment/__init__.py
|
|
|
133
133
|
src/velocity/payment/authorizenet_adapter.py
|
|
134
134
|
src/velocity/payment/base_adapter.py
|
|
135
135
|
src/velocity/payment/braintree_adapter.py
|
|
136
|
+
src/velocity/payment/charge_rules.py
|
|
136
137
|
src/velocity/payment/demo_profiles.py
|
|
137
138
|
src/velocity/payment/profiles.py
|
|
138
139
|
src/velocity/payment/router.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/app/tests/test_email_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/base_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/context_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/lambda_handler.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/data_service.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/mixins/web_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/aws/handlers/sqs_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/initializer.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/base/operators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/mysql/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/postgres/types.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlite/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/reserved.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/sql.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/servers/sqlserver/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/common.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_column.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_database.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_imports.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_result.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_row.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_sequence.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/postgres/test_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_postgres_unchanged.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_result_caching.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_result_sql_aware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_sql_builder.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_tablehelper.py
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/db/tests/test_view_helper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/misc/tests/test_original_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/authorizenet_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity/payment/braintree_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/src/velocity_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.232 → velocity_python-0.0.234}/tests/test_sys_modified_count_postgres_demo.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|