velocity-python 0.1.26__tar.gz → 0.1.28__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.1.26/src/velocity_python.egg-info → velocity_python-0.1.28}/PKG-INFO +1 -1
- {velocity_python-0.1.26 → velocity_python-0.1.28}/pyproject.toml +1 -1
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/__init__.py +1 -1
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/indexing.py +12 -2
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/authorizenet_adapter.py +185 -14
- velocity_python-0.1.28/src/velocity/payment/authorizenet_mirror.py +211 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/braintree_adapter.py +74 -28
- velocity_python-0.1.28/src/velocity/payment/braintree_mirror.py +210 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/stripe_adapter.py +129 -40
- velocity_python-0.1.28/src/velocity/payment/stripe_mirror.py +310 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity_python.egg-info/SOURCES.txt +5 -0
- velocity_python-0.1.28/tests/test_asset_indexing.py +103 -0
- velocity_python-0.1.28/tests/test_payment_authorizenet_adapter.py +173 -0
- velocity_python-0.1.28/tests/test_payment_braintree_adapter.py +182 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_payment_stripe_adapter.py +175 -1
- velocity_python-0.1.26/tests/test_payment_braintree_adapter.py +0 -77
- {velocity_python-0.1.26 → velocity_python-0.1.28}/LICENSE +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/README.md +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/setup.cfg +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/backfill.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/references.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/service.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/assets/usage_index.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/dirty_pipeline.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/s3.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/ssm_config.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/async_support.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/migrations.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/logging.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/pdf.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity_python.egg-info/entry_points.txt +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_asset_references.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_assets_service.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_async_support.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_concurrency_safety.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_connection_pool.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_connection_resilience.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_decorators.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_dirty_pipeline_fast_path.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_email_processing.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_n_plus_one.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_observability.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_pdf.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_prepared_statements.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_psycopg3_upgrade.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_query_cache.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_row_cache_staleness.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_row_dirty_tracking.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_schema_migrations.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_security_hardening.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_sqs_per_record_transactions.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_table_alter.py +0 -0
- {velocity_python-0.1.26 → velocity_python-0.1.28}/tests/test_where_clause_validation.py +0 -0
|
@@ -76,7 +76,11 @@ def reconcile_form_builder_template_asset_usages(
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def load_asset_usages(tx, *, source_table: str, source_sys_id: str) -> list[AssetUsage]:
|
|
79
|
-
|
|
79
|
+
usage_index = tx.table("asset_usage_index")
|
|
80
|
+
if not usage_index.exists():
|
|
81
|
+
return []
|
|
82
|
+
|
|
83
|
+
rows = usage_index.select(
|
|
80
84
|
where={
|
|
81
85
|
"source_table": source_table,
|
|
82
86
|
"source_sys_id": source_sys_id,
|
|
@@ -87,6 +91,9 @@ def load_asset_usages(tx, *, source_table: str, source_sys_id: str) -> list[Asse
|
|
|
87
91
|
|
|
88
92
|
def apply_asset_usage_reconciliation(tx, reconciliation: AssetUsageReconciliation) -> None:
|
|
89
93
|
table = tx.table("asset_usage_index")
|
|
94
|
+
if not table.exists():
|
|
95
|
+
return
|
|
96
|
+
|
|
90
97
|
for usage in reconciliation.to_create + reconciliation.to_refresh:
|
|
91
98
|
row = _asset_usage_to_row(usage)
|
|
92
99
|
table.upsert(
|
|
@@ -115,13 +122,16 @@ def resolve_asset_id_for_reference(tx, reference: AssetReference) -> str | None:
|
|
|
115
122
|
return reference.asset_id
|
|
116
123
|
|
|
117
124
|
images = tx.table("images")
|
|
125
|
+
if not images.exists():
|
|
126
|
+
return None
|
|
127
|
+
|
|
118
128
|
for candidate_key in _candidate_storage_keys(reference.storage_key):
|
|
119
129
|
row = images.find({"key": candidate_key})
|
|
120
130
|
asset_id = _extract_sys_id(row)
|
|
121
131
|
if asset_id:
|
|
122
132
|
return asset_id
|
|
123
133
|
|
|
124
|
-
if reference.url:
|
|
134
|
+
if reference.url and images.column("url").exists():
|
|
125
135
|
row = images.find({"url": reference.url})
|
|
126
136
|
asset_id = _extract_sys_id(row)
|
|
127
137
|
if asset_id:
|
{velocity_python-0.1.26 → velocity_python-0.1.28}/src/velocity/payment/authorizenet_adapter.py
RENAMED
|
@@ -29,6 +29,13 @@ from typing import Any, Dict, List, Optional
|
|
|
29
29
|
from authorizenet import apicontractsv1, apicontrollers
|
|
30
30
|
|
|
31
31
|
from .base_adapter import PaymentProcessorAdapter, ProcessorError
|
|
32
|
+
from .authorizenet_mirror import (
|
|
33
|
+
sync_client_payment_account_from_authorize_account,
|
|
34
|
+
upsert_authorize_account_record,
|
|
35
|
+
upsert_authorize_customer_profile_record,
|
|
36
|
+
upsert_authorize_payment_profile_record,
|
|
37
|
+
upsert_authorize_transaction_record,
|
|
38
|
+
)
|
|
32
39
|
|
|
33
40
|
logger = logging.getLogger(__name__)
|
|
34
41
|
|
|
@@ -132,20 +139,25 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
132
139
|
placeholder record so the routing layer can treat it uniformly.
|
|
133
140
|
"""
|
|
134
141
|
client_id = client_data["client_id"]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
payment_account["details_submitted"] = True
|
|
144
|
-
payment_account["requirements_data"] = {}
|
|
145
|
-
payment_account["capabilities"] = {
|
|
146
|
-
"card_payments": True,
|
|
147
|
-
"manual_settlement": True,
|
|
142
|
+
account = {
|
|
143
|
+
"client_id": client_id,
|
|
144
|
+
"processor_account_id": f"an_{client_id}",
|
|
145
|
+
"status": "active",
|
|
146
|
+
"charges_enabled": True,
|
|
147
|
+
"payouts_enabled": False,
|
|
148
|
+
"verification_status": "verified",
|
|
149
|
+
"metadata": {"account_type": "shared_merchant"},
|
|
148
150
|
}
|
|
151
|
+
upsert_authorize_account_record(
|
|
152
|
+
tx,
|
|
153
|
+
account,
|
|
154
|
+
source="api:authorizenet_adapter.create_account",
|
|
155
|
+
)
|
|
156
|
+
sync_client_payment_account_from_authorize_account(
|
|
157
|
+
tx,
|
|
158
|
+
account,
|
|
159
|
+
client_id=client_id,
|
|
160
|
+
)
|
|
149
161
|
|
|
150
162
|
return {
|
|
151
163
|
"processor_account_id": f"an_{client_id}",
|
|
@@ -161,7 +173,7 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
161
173
|
"""
|
|
162
174
|
Authorize.Net shared merchant is always active if credentials are valid.
|
|
163
175
|
"""
|
|
164
|
-
|
|
176
|
+
account = {
|
|
165
177
|
"account_id": processor_account_id,
|
|
166
178
|
"status": "active",
|
|
167
179
|
"charges_enabled": True,
|
|
@@ -172,6 +184,26 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
172
184
|
"verification_status": "verified",
|
|
173
185
|
"metadata": {"account_type": "shared_merchant"},
|
|
174
186
|
}
|
|
187
|
+
payment_account = tx.table("client_payment_accounts").find(
|
|
188
|
+
{
|
|
189
|
+
"processor_account_id": processor_account_id,
|
|
190
|
+
"processor_type": "authorize_net",
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
client_id = payment_account.get("client_id") if payment_account else None
|
|
194
|
+
if client_id:
|
|
195
|
+
account["client_id"] = client_id
|
|
196
|
+
upsert_authorize_account_record(
|
|
197
|
+
tx,
|
|
198
|
+
account,
|
|
199
|
+
source="api:authorizenet_adapter.get_account_status",
|
|
200
|
+
)
|
|
201
|
+
sync_client_payment_account_from_authorize_account(
|
|
202
|
+
tx,
|
|
203
|
+
account,
|
|
204
|
+
client_id=client_id,
|
|
205
|
+
)
|
|
206
|
+
return account
|
|
175
207
|
|
|
176
208
|
def create_onboarding_link(
|
|
177
209
|
self, tx, processor_account_id: str, return_url: str, refresh_url: str
|
|
@@ -225,12 +257,33 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
225
257
|
parts = e.error_message.split()
|
|
226
258
|
for part in parts:
|
|
227
259
|
if part.strip().isdigit():
|
|
260
|
+
upsert_authorize_customer_profile_record(
|
|
261
|
+
tx,
|
|
262
|
+
{
|
|
263
|
+
"customer_profile_id": part.strip(),
|
|
264
|
+
"email_address": email_address,
|
|
265
|
+
"description": customer_data.get(
|
|
266
|
+
"name", email_address
|
|
267
|
+
),
|
|
268
|
+
},
|
|
269
|
+
source="api:authorizenet_adapter.get_or_create_customer_profile",
|
|
270
|
+
)
|
|
228
271
|
return {
|
|
229
272
|
"customer_profile_id": part.strip(),
|
|
230
273
|
"created": False,
|
|
231
274
|
}
|
|
232
275
|
raise
|
|
233
276
|
|
|
277
|
+
upsert_authorize_customer_profile_record(
|
|
278
|
+
tx,
|
|
279
|
+
{
|
|
280
|
+
"customer_profile_id": response["customerProfileId"],
|
|
281
|
+
"email_address": email_address,
|
|
282
|
+
"description": customer_data.get("name", email_address),
|
|
283
|
+
},
|
|
284
|
+
source="api:authorizenet_adapter.get_or_create_customer_profile",
|
|
285
|
+
)
|
|
286
|
+
|
|
234
287
|
return {
|
|
235
288
|
"customer_profile_id": response["customerProfileId"],
|
|
236
289
|
"created": True,
|
|
@@ -287,6 +340,24 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
287
340
|
|
|
288
341
|
controller = apicontrollers.createCustomerPaymentProfileController(request)
|
|
289
342
|
response = self._execute(controller)
|
|
343
|
+
upsert_authorize_payment_profile_record(
|
|
344
|
+
tx,
|
|
345
|
+
{
|
|
346
|
+
"customer_profile_id": customer_profile_id,
|
|
347
|
+
"payment_profile_id": response["customerPaymentProfileId"],
|
|
348
|
+
"last4": str(payment_data.get("card_number") or "")[-4:] or None,
|
|
349
|
+
"expiration_date": payment_data.get("expiration_date"),
|
|
350
|
+
"billing_first_name": payment_data.get("first_name"),
|
|
351
|
+
"billing_last_name": payment_data.get("last_name"),
|
|
352
|
+
"billing_address": payment_data.get("address"),
|
|
353
|
+
"billing_city": payment_data.get("city"),
|
|
354
|
+
"billing_state": payment_data.get("state"),
|
|
355
|
+
"billing_zip": payment_data.get("zip"),
|
|
356
|
+
"is_default": payment_data.get("set_default", True),
|
|
357
|
+
"metadata": payment_data.get("metadata") or {},
|
|
358
|
+
},
|
|
359
|
+
source="api:authorizenet_adapter.attach_payment_method",
|
|
360
|
+
)
|
|
290
361
|
|
|
291
362
|
return {
|
|
292
363
|
"customer_profile_id": customer_profile_id,
|
|
@@ -326,6 +397,16 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
326
397
|
else:
|
|
327
398
|
raise
|
|
328
399
|
|
|
400
|
+
upsert_authorize_payment_profile_record(
|
|
401
|
+
tx,
|
|
402
|
+
{
|
|
403
|
+
"customer_profile_id": customer_profile_id,
|
|
404
|
+
"payment_profile_id": payment_method_id,
|
|
405
|
+
"detached": True,
|
|
406
|
+
},
|
|
407
|
+
source="api:authorizenet_adapter.detach_payment_method",
|
|
408
|
+
)
|
|
409
|
+
|
|
329
410
|
return {"payment_profile_id": payment_method_id, "detached": True}
|
|
330
411
|
|
|
331
412
|
def delete_customer_profile(self, tx, customer_profile_id: str) -> Dict[str, Any]:
|
|
@@ -343,6 +424,12 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
343
424
|
else:
|
|
344
425
|
raise
|
|
345
426
|
|
|
427
|
+
upsert_authorize_customer_profile_record(
|
|
428
|
+
tx,
|
|
429
|
+
{"customer_profile_id": customer_profile_id, "deleted": True},
|
|
430
|
+
source="api:authorizenet_adapter.delete_customer_profile",
|
|
431
|
+
)
|
|
432
|
+
|
|
346
433
|
return {"customer_profile_id": customer_profile_id, "deleted": True}
|
|
347
434
|
|
|
348
435
|
# ========================================================================
|
|
@@ -385,6 +472,24 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
385
472
|
response = self._execute(controller)
|
|
386
473
|
trans = response.get("transactionResponse", {})
|
|
387
474
|
code = int(trans.get("responseCode", 3))
|
|
475
|
+
status = "authorized" if RESPONSE_CODES.get(code) == "Approved" else "failed"
|
|
476
|
+
upsert_authorize_transaction_record(
|
|
477
|
+
tx,
|
|
478
|
+
{
|
|
479
|
+
"processor_transaction_id": trans.get("transId"),
|
|
480
|
+
"amount": float(amount_dollars),
|
|
481
|
+
"status": status,
|
|
482
|
+
"reason_for_transaction": payment_data.get("description"),
|
|
483
|
+
"remote_authcode": trans.get("authCode"),
|
|
484
|
+
"remote_responsecode": code,
|
|
485
|
+
"supported_id": payment_data.get("client_id"),
|
|
486
|
+
"supported_name": payment_data.get("description"),
|
|
487
|
+
"email_address": payment_data.get("customer_email")
|
|
488
|
+
or payment_data.get("donor_email"),
|
|
489
|
+
"raw_payload": response,
|
|
490
|
+
},
|
|
491
|
+
source="api:authorizenet_adapter.authorize_payment",
|
|
492
|
+
)
|
|
388
493
|
|
|
389
494
|
if RESPONSE_CODES.get(code) == "Approved":
|
|
390
495
|
return {
|
|
@@ -492,6 +597,24 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
492
597
|
response = self._execute(controller)
|
|
493
598
|
trans = response.get("transactionResponse", {})
|
|
494
599
|
code = int(trans.get("responseCode", 3))
|
|
600
|
+
status = RESPONSE_CODES.get(code, "Error")
|
|
601
|
+
upsert_authorize_transaction_record(
|
|
602
|
+
tx,
|
|
603
|
+
{
|
|
604
|
+
"processor_transaction_id": trans.get("transId"),
|
|
605
|
+
"amount": float(amount_dollars),
|
|
606
|
+
"status": status,
|
|
607
|
+
"reason_for_transaction": order.description if client_id or campaign else None,
|
|
608
|
+
"remote_authcode": trans.get("authCode"),
|
|
609
|
+
"remote_responsecode": code,
|
|
610
|
+
"supported_id": client_id or None,
|
|
611
|
+
"supported_name": campaign or None,
|
|
612
|
+
"email_address": payment_data.get("customer_email")
|
|
613
|
+
or payment_data.get("donor_email"),
|
|
614
|
+
"raw_payload": response,
|
|
615
|
+
},
|
|
616
|
+
source="api:authorizenet_adapter.charge_stored_payment_method",
|
|
617
|
+
)
|
|
495
618
|
|
|
496
619
|
if RESPONSE_CODES.get(code) == "Approved":
|
|
497
620
|
return {
|
|
@@ -581,6 +704,23 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
581
704
|
response = self._execute(controller)
|
|
582
705
|
trans = response.get("transactionResponse", {})
|
|
583
706
|
code = int(trans.get("responseCode", 3))
|
|
707
|
+
upsert_authorize_transaction_record(
|
|
708
|
+
tx,
|
|
709
|
+
{
|
|
710
|
+
"processor_transaction_id": trans.get("transId")
|
|
711
|
+
or processor_transaction_id,
|
|
712
|
+
"amount": float(decimal.Decimal(amount) / 100)
|
|
713
|
+
if amount is not None
|
|
714
|
+
else None,
|
|
715
|
+
"status": "captured"
|
|
716
|
+
if RESPONSE_CODES.get(code) == "Approved"
|
|
717
|
+
else "failed",
|
|
718
|
+
"remote_authcode": trans.get("authCode"),
|
|
719
|
+
"remote_responsecode": code,
|
|
720
|
+
"raw_payload": response,
|
|
721
|
+
},
|
|
722
|
+
source="api:authorizenet_adapter.capture_payment",
|
|
723
|
+
)
|
|
584
724
|
|
|
585
725
|
if RESPONSE_CODES.get(code) == "Approved":
|
|
586
726
|
captured_cents = amount if amount is not None else 0
|
|
@@ -635,6 +775,20 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
635
775
|
response = self._execute(controller)
|
|
636
776
|
trans = response.get("transactionResponse", {})
|
|
637
777
|
code = int(trans.get("responseCode", 3))
|
|
778
|
+
upsert_authorize_transaction_record(
|
|
779
|
+
tx,
|
|
780
|
+
{
|
|
781
|
+
"processor_transaction_id": trans.get("transId")
|
|
782
|
+
or processor_transaction_id,
|
|
783
|
+
"status": "cancelled"
|
|
784
|
+
if RESPONSE_CODES.get(code) == "Approved"
|
|
785
|
+
else "failed",
|
|
786
|
+
"remote_authcode": trans.get("authCode"),
|
|
787
|
+
"remote_responsecode": code,
|
|
788
|
+
"raw_payload": response,
|
|
789
|
+
},
|
|
790
|
+
source="api:authorizenet_adapter.cancel_payment",
|
|
791
|
+
)
|
|
638
792
|
|
|
639
793
|
if RESPONSE_CODES.get(code) == "Approved":
|
|
640
794
|
return {
|
|
@@ -695,6 +849,23 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
695
849
|
response = self._execute(controller)
|
|
696
850
|
trans = response.get("transactionResponse", {})
|
|
697
851
|
code = int(trans.get("responseCode", 3))
|
|
852
|
+
upsert_authorize_transaction_record(
|
|
853
|
+
tx,
|
|
854
|
+
{
|
|
855
|
+
"processor_transaction_id": trans.get("transId")
|
|
856
|
+
or processor_charge_id,
|
|
857
|
+
"amount": float(decimal.Decimal(amount) / 100)
|
|
858
|
+
if amount is not None
|
|
859
|
+
else None,
|
|
860
|
+
"status": "Refunded"
|
|
861
|
+
if RESPONSE_CODES.get(code) == "Approved"
|
|
862
|
+
else "Error",
|
|
863
|
+
"remote_authcode": trans.get("authCode"),
|
|
864
|
+
"remote_responsecode": code,
|
|
865
|
+
"raw_payload": response,
|
|
866
|
+
},
|
|
867
|
+
source="api:authorizenet_adapter.refund_payment",
|
|
868
|
+
)
|
|
698
869
|
|
|
699
870
|
if RESPONSE_CODES.get(code) == "Approved":
|
|
700
871
|
return {
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _get_value(data: Any, key: str, default: Any = None) -> Any:
|
|
7
|
+
if isinstance(data, dict):
|
|
8
|
+
return data.get(key, default)
|
|
9
|
+
return getattr(data, key, default)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _to_jsonable(value: Any) -> Any:
|
|
13
|
+
if value is None or isinstance(value, (str, int, float, bool)):
|
|
14
|
+
return value
|
|
15
|
+
if isinstance(value, dict):
|
|
16
|
+
return {str(key): _to_jsonable(item) for key, item in value.items()}
|
|
17
|
+
if isinstance(value, (list, tuple, set)):
|
|
18
|
+
return [_to_jsonable(item) for item in value]
|
|
19
|
+
if hasattr(value, "__dict__"):
|
|
20
|
+
return {
|
|
21
|
+
str(key): _to_jsonable(item)
|
|
22
|
+
for key, item in vars(value).items()
|
|
23
|
+
if not str(key).startswith("_")
|
|
24
|
+
}
|
|
25
|
+
return str(value)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _json_dumps(value: Any) -> Optional[str]:
|
|
29
|
+
if value is None:
|
|
30
|
+
return None
|
|
31
|
+
return json.dumps(_to_jsonable(value), default=str)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _table(tx, table_name: str):
|
|
35
|
+
if tx is None:
|
|
36
|
+
return None
|
|
37
|
+
try:
|
|
38
|
+
table = tx.table(table_name)
|
|
39
|
+
except Exception:
|
|
40
|
+
return None
|
|
41
|
+
try:
|
|
42
|
+
if hasattr(table, "exists") and not table.exists():
|
|
43
|
+
return None
|
|
44
|
+
except Exception:
|
|
45
|
+
pass
|
|
46
|
+
return table
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _upsert(tx, table_name: str, payload: Dict[str, Any], key: Dict[str, Any]):
|
|
50
|
+
table = _table(tx, table_name)
|
|
51
|
+
if not table:
|
|
52
|
+
return None
|
|
53
|
+
table.upsert(payload, key)
|
|
54
|
+
return payload
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _now() -> datetime:
|
|
58
|
+
return datetime.now(timezone.utc)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def upsert_authorize_account_record(
|
|
62
|
+
tx, account: Dict[str, Any], *, source: str = "api:authorizenet"
|
|
63
|
+
) -> Optional[Dict[str, Any]]:
|
|
64
|
+
processor_account_id = _get_value(account, "processor_account_id") or _get_value(
|
|
65
|
+
account, "account_id"
|
|
66
|
+
)
|
|
67
|
+
if not processor_account_id:
|
|
68
|
+
return None
|
|
69
|
+
payload = {
|
|
70
|
+
"processor_account_id": processor_account_id,
|
|
71
|
+
"client_id": _get_value(account, "client_id"),
|
|
72
|
+
"account_status": _get_value(account, "status"),
|
|
73
|
+
"charges_enabled": _get_value(account, "charges_enabled"),
|
|
74
|
+
"payouts_enabled": _get_value(account, "payouts_enabled"),
|
|
75
|
+
"verification_status": _get_value(account, "verification_status"),
|
|
76
|
+
"metadata": _to_jsonable(_get_value(account, "metadata") or {}),
|
|
77
|
+
"raw_payload": _to_jsonable(account),
|
|
78
|
+
"sys_modified_by": source,
|
|
79
|
+
"sys_dirty": True,
|
|
80
|
+
}
|
|
81
|
+
return _upsert(
|
|
82
|
+
tx,
|
|
83
|
+
"authorize_accounts",
|
|
84
|
+
payload,
|
|
85
|
+
{"processor_account_id": processor_account_id},
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def sync_client_payment_account_from_authorize_account(
|
|
90
|
+
tx, account: Dict[str, Any], *, client_id: Any
|
|
91
|
+
):
|
|
92
|
+
if not client_id:
|
|
93
|
+
return None
|
|
94
|
+
processor_account_id = _get_value(account, "processor_account_id") or _get_value(
|
|
95
|
+
account, "account_id"
|
|
96
|
+
)
|
|
97
|
+
if not processor_account_id:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
payload = {
|
|
101
|
+
"client_id": client_id,
|
|
102
|
+
"processor_type": "authorize_net",
|
|
103
|
+
"processor_account_id": processor_account_id,
|
|
104
|
+
"account_status": _get_value(account, "status") or "active",
|
|
105
|
+
"capabilities": {
|
|
106
|
+
"card_payments": True,
|
|
107
|
+
"manual_settlement": True,
|
|
108
|
+
},
|
|
109
|
+
"configuration": {
|
|
110
|
+
"verification_status": _get_value(account, "verification_status"),
|
|
111
|
+
},
|
|
112
|
+
"metadata": _to_jsonable(_get_value(account, "metadata") or {}),
|
|
113
|
+
"onboarding_complete": True,
|
|
114
|
+
"charges_enabled": True,
|
|
115
|
+
"payouts_enabled": False,
|
|
116
|
+
"details_submitted": True,
|
|
117
|
+
}
|
|
118
|
+
return _upsert(
|
|
119
|
+
tx,
|
|
120
|
+
"client_payment_accounts",
|
|
121
|
+
payload,
|
|
122
|
+
{"client_id": client_id, "processor_type": "authorize_net"},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def upsert_authorize_customer_profile_record(
|
|
127
|
+
tx, customer_profile: Dict[str, Any], *, source: str = "api:authorizenet"
|
|
128
|
+
) -> Optional[Dict[str, Any]]:
|
|
129
|
+
customer_profile_id = _get_value(customer_profile, "customer_profile_id") or _get_value(
|
|
130
|
+
customer_profile, "id"
|
|
131
|
+
)
|
|
132
|
+
if not customer_profile_id:
|
|
133
|
+
return None
|
|
134
|
+
payload = {
|
|
135
|
+
"customer_profile_id": customer_profile_id,
|
|
136
|
+
"email_address": _get_value(customer_profile, "email_address")
|
|
137
|
+
or _get_value(customer_profile, "email"),
|
|
138
|
+
"description": _get_value(customer_profile, "description"),
|
|
139
|
+
"deleted": bool(_get_value(customer_profile, "deleted")),
|
|
140
|
+
"metadata": _to_jsonable(_get_value(customer_profile, "metadata") or {}),
|
|
141
|
+
"raw_payload": _to_jsonable(customer_profile),
|
|
142
|
+
"lastupdateddate": _now(),
|
|
143
|
+
"sys_modified_by": source,
|
|
144
|
+
"sys_dirty": True,
|
|
145
|
+
}
|
|
146
|
+
return _upsert(
|
|
147
|
+
tx,
|
|
148
|
+
"authorize_customer_profiles",
|
|
149
|
+
payload,
|
|
150
|
+
{"customer_profile_id": customer_profile_id},
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def upsert_authorize_payment_profile_record(
|
|
155
|
+
tx, payment_profile: Dict[str, Any], *, source: str = "api:authorizenet"
|
|
156
|
+
) -> Optional[Dict[str, Any]]:
|
|
157
|
+
payment_profile_id = _get_value(payment_profile, "payment_profile_id") or _get_value(
|
|
158
|
+
payment_profile, "id"
|
|
159
|
+
)
|
|
160
|
+
if not payment_profile_id:
|
|
161
|
+
return None
|
|
162
|
+
payload = {
|
|
163
|
+
"payment_profile_id": payment_profile_id,
|
|
164
|
+
"customer_profile_id": _get_value(payment_profile, "customer_profile_id"),
|
|
165
|
+
"last4": _get_value(payment_profile, "last4"),
|
|
166
|
+
"expiration_date": _get_value(payment_profile, "expiration_date"),
|
|
167
|
+
"billing_first_name": _get_value(payment_profile, "billing_first_name"),
|
|
168
|
+
"billing_last_name": _get_value(payment_profile, "billing_last_name"),
|
|
169
|
+
"billing_address": _get_value(payment_profile, "billing_address"),
|
|
170
|
+
"billing_city": _get_value(payment_profile, "billing_city"),
|
|
171
|
+
"billing_state": _get_value(payment_profile, "billing_state"),
|
|
172
|
+
"billing_zip": _get_value(payment_profile, "billing_zip"),
|
|
173
|
+
"is_default": _get_value(payment_profile, "is_default"),
|
|
174
|
+
"detached": bool(_get_value(payment_profile, "detached")),
|
|
175
|
+
"metadata": _to_jsonable(_get_value(payment_profile, "metadata") or {}),
|
|
176
|
+
"raw_payload": _to_jsonable(payment_profile),
|
|
177
|
+
"lastupdateddate": _now(),
|
|
178
|
+
"sys_modified_by": source,
|
|
179
|
+
"sys_dirty": True,
|
|
180
|
+
}
|
|
181
|
+
return _upsert(
|
|
182
|
+
tx,
|
|
183
|
+
"authorize_payment_profiles",
|
|
184
|
+
payload,
|
|
185
|
+
{"payment_profile_id": payment_profile_id},
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def upsert_authorize_transaction_record(
|
|
190
|
+
tx, transaction: Dict[str, Any], *, source: str = "api:authorizenet"
|
|
191
|
+
) -> Optional[Dict[str, Any]]:
|
|
192
|
+
remote_transid = _get_value(transaction, "remote_transid") or _get_value(
|
|
193
|
+
transaction, "processor_transaction_id"
|
|
194
|
+
)
|
|
195
|
+
if not remote_transid:
|
|
196
|
+
return None
|
|
197
|
+
payload = {
|
|
198
|
+
"remote_transid": remote_transid,
|
|
199
|
+
"amount": _get_value(transaction, "amount"),
|
|
200
|
+
"status": _get_value(transaction, "status"),
|
|
201
|
+
"lastupdateddate": _now(),
|
|
202
|
+
"createddate": _get_value(transaction, "createddate") or _now(),
|
|
203
|
+
"reason_for_transaction": _get_value(transaction, "reason_for_transaction"),
|
|
204
|
+
"remote_authcode": _get_value(transaction, "remote_authcode"),
|
|
205
|
+
"remote_responsecode": _get_value(transaction, "remote_responsecode"),
|
|
206
|
+
"supported_id": _get_value(transaction, "supported_id"),
|
|
207
|
+
"supported_name": _get_value(transaction, "supported_name"),
|
|
208
|
+
"email_address": _get_value(transaction, "email_address"),
|
|
209
|
+
"reconcile_response": _json_dumps(_get_value(transaction, "raw_payload") or transaction),
|
|
210
|
+
}
|
|
211
|
+
return _upsert(tx, "authorize_transactions", payload, {"remote_transid": remote_transid})
|