velocity-python 0.2.0__tar.gz → 0.2.1__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.2.0/src/velocity_python.egg-info → velocity_python-0.2.1}/PKG-INFO +1 -1
- {velocity_python-0.2.0 → velocity_python-0.2.1}/pyproject.toml +1 -1
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/__init__.py +1 -1
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_sms.py +7 -4
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/pdf.py +10 -3
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/__init__.py +2 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/authorizenet_adapter.py +306 -14
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/base_adapter.py +207 -2
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/braintree_adapter.py +150 -13
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/stripe_adapter.py +190 -7
- {velocity_python-0.2.0 → velocity_python-0.2.1/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity_python.egg-info/SOURCES.txt +1 -0
- velocity_python-0.2.1/tests/test_payment_charge_reference.py +1367 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pdf.py +31 -11
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_result_returning.py +7 -2
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_session_control.py +10 -11
- {velocity_python-0.2.0 → velocity_python-0.2.1}/LICENSE +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/README.md +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/setup.cfg +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/backfill.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/indexing.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/references.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/service.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/assets/usage_index.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/blobs.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/base.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/dispatch.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/infra.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/jobs.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/provisioning.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/retention.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/security.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/capabilities/single_session.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/ci_gate.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/config.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/frontend_checks.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/operations.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/policies.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/reconcile.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/deploy/targets.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/dirty_pipeline.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/email.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/facets.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/failures.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/feature_flags.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/masquerade.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/audit_trail.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/client_errors.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/client_input.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/job_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/row_scoped.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/session_control.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/job_lifecycle.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/job_results.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/ops.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/queue_defaults.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/s3.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/schema.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/sms.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/ssm_config.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_deploy_least_privilege.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_deploy_policies.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_deploy_policy_size.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_deploy_reconcile.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_email.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/async_support.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/jsonproxy.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/lazy_engine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/fragments.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/maintenance.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/migrations.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/conftest.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/tunnel.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/logging.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_mail_send.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/core/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/core/capabilities.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/core/store.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/core/where.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/exceptions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/base/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/cassandra/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/cassandra/translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/couchbase/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/couchbase/translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/dynamodb/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/dynamodb/translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/elasticsearch/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/elasticsearch/translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/memory/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/mongodb/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/mongodb/translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/nosql/servers/redis/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/_mirror_core.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/authorizenet_mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/braintree_mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/money.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/plaid_api.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/plaid_webhook.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/redact.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/schema.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/stripe_mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/testing/__init__.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/testing/fake_db.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity_python.egg-info/entry_points.txt +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_access_error_403.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_activity_tracking_aborted_tx.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_amplify_redirects.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_asset_indexing.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_asset_references.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_assets_service.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_async_support.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_audit_mixin.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_aws_package_hygiene.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_blob_store.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_capabilities.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_capability_catalog.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_check_changelog.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_ci_gate.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_client_errors_mixin.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_client_input_contract_export.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_client_sql_boundary.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_client_table_gate_case_and_pointers.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_cognito_user_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_column_tx_arg.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_concurrency_safety.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_connection_pool.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_connection_resilience.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_context_flags_loader.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_context_job_descriptions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_context_queue_job.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_conv_combine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_data_service_query_cap.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_data_service_renumber.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_data_service_row_number.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_data_service_save_as.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_data_service_security_gates.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_db_credentials_ssm_cascade.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_db_maintenance.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_db_tunnel.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_declared_column_types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_decorators.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_delete_hook_fk_blocked.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_deploy_config_fields.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_deploy_engine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_deploy_frontend_checks.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_deploy_operations_queue.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_deploy_policies.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_dirty_pipeline_fast_path.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_dlq_constant.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_docs_snippets.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_email_processing.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_enqueue_metric_namespace.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_enqueue_send_failures.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_ensure_infrastructure.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_export_workbook.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_facets.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_facets_and_where.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_failures.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_feature_flags.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_get_cognito_user_provider.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_http_handler_rollback.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_identifier_injection_guard.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_job_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_job_lifecycle.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_job_results.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_json_columns.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_jsonb_dict_adapter.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_lambda_handler_masquerade.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_lambda_handler_user_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_lazy_engine.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_masquerade_grant.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_merge_on_conflict.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_mirror_upsert_public.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_n_plus_one.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_dynamodb.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_memory.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_mongodb.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_redis.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_translation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_nosql_where.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_observability.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_on_action_default.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_on_commit.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_ops.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_audit_fixes.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_authorizenet_adapter.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_braintree_mirror.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_business_agnostic.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_extra_bounds.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_lazy_imports.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_mirror_empty_table.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_bulk_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_capability_types.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_ensure_infrastructure.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_get_tables.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_pointer_joins.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pgserver_search_export.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_plaid_api.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_plaid_webhook.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_pointer_join_sql.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_postgres_initializer_config.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_postgres_py_type.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_prepared_statements.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_psycopg3_upgrade.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_query_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_query_missing_table_unlocked.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_raw_sql_prefix_policy.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_read_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_readme_imports.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_response.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_restricted_direct_tables.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_retry_side_effect_guard.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_return_default_safety.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_row_cache_staleness.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_row_scoped_data_service.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_s3_bucket_config.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_s3_list_client_files.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_s3_upload.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_schema_lock_config_other_backends.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_schema_migrations.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_search_paging_export.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_security_capability.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_security_hardening.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_server_cursor.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_single_autocommit_safety.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_single_session_capability.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_sms_twilio_signature.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_sqlite_backend.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_sqs_per_record_transactions.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_ssm_config.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_ssm_config_require.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_store_user_data.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_table_alter.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_table_claim.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_table_find_cache.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_table_purge.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_testing_fake_db.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_transaction_class_wrapping.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_transaction_commit_and_ownership.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_transaction_edge_cases.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_tx_lifecycle_retry.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_tx_read_cache_and_bulk.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_user_not_provisioned.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_where_clause_validation.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_write_hook_create_flow.py +0 -0
- {velocity_python-0.2.0 → velocity_python-0.2.1}/tests/test_write_hook_empty_strings.py +0 -0
|
@@ -55,10 +55,13 @@ class TestParseInboundEvent(unittest.TestCase):
|
|
|
55
55
|
)
|
|
56
56
|
messages = parse_inbound_event(event)
|
|
57
57
|
self.assertEqual(len(messages), 2)
|
|
58
|
-
self.assertEqual(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
self.assertEqual(
|
|
59
|
+
messages[1].media_urls,
|
|
60
|
+
[
|
|
61
|
+
"s3://bucket/media/one.jpg",
|
|
62
|
+
"s3://bucket/media/two.jpg",
|
|
63
|
+
],
|
|
64
|
+
)
|
|
62
65
|
|
|
63
66
|
def test_bare_payload_dict(self):
|
|
64
67
|
messages = parse_inbound_event(_payload())
|
|
@@ -214,7 +214,10 @@ def page_css(page: PageOptions) -> str:
|
|
|
214
214
|
size = _css_page_size(page)
|
|
215
215
|
top, right, bottom, left = page.margins()
|
|
216
216
|
parts = [f"size: {size};", f"margin: {top} {right} {bottom} {left};"]
|
|
217
|
-
for slot, text in (
|
|
217
|
+
for slot, text in (
|
|
218
|
+
("bottom-right", page.footer_right),
|
|
219
|
+
("bottom-center", page.footer_center),
|
|
220
|
+
):
|
|
218
221
|
if text:
|
|
219
222
|
parts.append(
|
|
220
223
|
f"@{slot} {{ content: {_footer_content(text)}; "
|
|
@@ -258,7 +261,9 @@ _RENDERERS: Dict[str, BasePdfRenderer] = {
|
|
|
258
261
|
}
|
|
259
262
|
|
|
260
263
|
|
|
261
|
-
def register_renderer(
|
|
264
|
+
def register_renderer(
|
|
265
|
+
name: str, renderer: BasePdfRenderer, *, preferred: bool = False
|
|
266
|
+
) -> None:
|
|
262
267
|
"""Add (or replace) a backend. ``preferred=True`` makes it the first choice
|
|
263
268
|
for auto-selection."""
|
|
264
269
|
key = name.strip().lower()
|
|
@@ -331,7 +336,9 @@ def html_to_pdf(
|
|
|
331
336
|
footer_center=footer_center,
|
|
332
337
|
footer_font_size=footer_font_size,
|
|
333
338
|
)
|
|
334
|
-
return get_renderer(engine).render(
|
|
339
|
+
return get_renderer(engine).render(
|
|
340
|
+
html, page, base_url=base_url, extra_css=extra_css
|
|
341
|
+
)
|
|
335
342
|
|
|
336
343
|
|
|
337
344
|
def _inject_css(html: str, css: str) -> str:
|
|
@@ -21,6 +21,7 @@ StripeAdapter`` still works and raises ImportError when the SDK is missing;
|
|
|
21
21
|
|
|
22
22
|
from .base_adapter import (
|
|
23
23
|
OUTCOME_UNKNOWN,
|
|
24
|
+
ChargeReferenceAnomaly,
|
|
24
25
|
PaymentProcessorAdapter,
|
|
25
26
|
ProcessorError,
|
|
26
27
|
ProcessorOutcomeUnknown,
|
|
@@ -38,6 +39,7 @@ __all__ = [
|
|
|
38
39
|
"PaymentProcessorAdapter",
|
|
39
40
|
"ProcessorError",
|
|
40
41
|
"ProcessorOutcomeUnknown",
|
|
42
|
+
"ChargeReferenceAnomaly",
|
|
41
43
|
"OUTCOME_UNKNOWN",
|
|
42
44
|
# Adapters
|
|
43
45
|
"StripeAdapter",
|
{velocity_python-0.2.0 → velocity_python-0.2.1}/src/velocity/payment/authorizenet_adapter.py
RENAMED
|
@@ -30,11 +30,14 @@ from authorizenet import apicontractsv1, apicontrollers
|
|
|
30
30
|
from .base_adapter import (
|
|
31
31
|
PaymentProcessorAdapter,
|
|
32
32
|
ProcessorError,
|
|
33
|
+
_as_utc,
|
|
33
34
|
_require_amount,
|
|
34
35
|
_validate_partial_amount,
|
|
36
|
+
fit_reference,
|
|
35
37
|
mark_external_side_effect,
|
|
38
|
+
payment_reference,
|
|
36
39
|
)
|
|
37
|
-
from .money import cents_to_decimal
|
|
40
|
+
from .money import cents_to_decimal, to_cents
|
|
38
41
|
from .redact import normalize_card_number, scrub
|
|
39
42
|
from .authorizenet_mirror import (
|
|
40
43
|
build_payment_account_fields_from_authorize_account,
|
|
@@ -52,6 +55,75 @@ logger = logging.getLogger(__name__)
|
|
|
52
55
|
logging.getLogger("authorizenet.sdk").setLevel(logging.CRITICAL + 1)
|
|
53
56
|
logging.getLogger("pyxb").setLevel(logging.WARNING)
|
|
54
57
|
|
|
58
|
+
#: ``order.invoiceNumber`` and the request ``refId`` are each at most 20
|
|
59
|
+
#: characters (AnetApiSchema.xsd; the SDK rejects longer values).
|
|
60
|
+
INVOICE_NUMBER_MAX_LENGTH = 20
|
|
61
|
+
REF_ID_MAX_LENGTH = 20
|
|
62
|
+
|
|
63
|
+
#: getTransactionList / getUnsettledTransactionList page size (schema max 1000).
|
|
64
|
+
_PAGE_LIMIT = 1000
|
|
65
|
+
#: getSettledBatchList accepts at most 31 days per request.
|
|
66
|
+
_BATCH_WINDOW = timedelta(days=30)
|
|
67
|
+
#: Look-back when find_charge_by_reference gets no ``since``.
|
|
68
|
+
DEFAULT_REFERENCE_LOOKBACK = timedelta(days=31)
|
|
69
|
+
|
|
70
|
+
#: transactionStatus values meaning "no money moved / none will": ignored by a
|
|
71
|
+
#: lookup by reference. Refund statuses are skipped too (they are credits).
|
|
72
|
+
_DEAD_STATUSES = frozenset(
|
|
73
|
+
{
|
|
74
|
+
"declined",
|
|
75
|
+
"voided",
|
|
76
|
+
"expired",
|
|
77
|
+
"generalError",
|
|
78
|
+
"failedReview",
|
|
79
|
+
"settlementError",
|
|
80
|
+
"communicationError",
|
|
81
|
+
"refundSettledSuccessfully",
|
|
82
|
+
"refundPendingSettlement",
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
#: Live but undecided (fraud review): returned with ``success=False``.
|
|
86
|
+
_PENDING_STATUSES = frozenset(
|
|
87
|
+
{"FDSPendingReview", "FDSAuthorizedPendingReview", "underReview"}
|
|
88
|
+
)
|
|
89
|
+
#: An authOnlyTransaction not yet captured (``authorize_payment``'s result).
|
|
90
|
+
_AUTHORIZED_STATUSES = frozenset({"authorizedPendingCapture"})
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _lookup_status(transaction_status: Any) -> str:
|
|
94
|
+
"""A live ``transactionStatus`` in the charge path's vocabulary.
|
|
95
|
+
|
|
96
|
+
Fraud review -> ``"Held for Review"`` (response code 4), an uncaptured
|
|
97
|
+
authOnly -> ``"authorized"`` (as ``authorize_payment`` reports it), every
|
|
98
|
+
other live status (captured, settled, approved after review...) ->
|
|
99
|
+
``"Approved"`` (response code 1).
|
|
100
|
+
"""
|
|
101
|
+
if transaction_status in _PENDING_STATUSES:
|
|
102
|
+
return RESPONSE_CODES[4]
|
|
103
|
+
if transaction_status in _AUTHORIZED_STATUSES:
|
|
104
|
+
return "authorized"
|
|
105
|
+
return RESPONSE_CODES[1]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _invoice_number(payment_data: Dict[str, Any]) -> Optional[str]:
|
|
109
|
+
"""The ``order.invoiceNumber`` for ``payment_data``'s reference, or None.
|
|
110
|
+
|
|
111
|
+
The same value is sent as the request ``refId`` (also 20 characters).
|
|
112
|
+
"""
|
|
113
|
+
reference = payment_reference(payment_data)
|
|
114
|
+
return fit_reference(reference, INVOICE_NUMBER_MAX_LENGTH) if reference else None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _as_list(container: Any, key: str) -> List[Dict[str, Any]]:
|
|
118
|
+
"""xmltodict gives one child as a dict and several as a list."""
|
|
119
|
+
if not isinstance(container, dict):
|
|
120
|
+
return []
|
|
121
|
+
value = container.get(key)
|
|
122
|
+
if value is None:
|
|
123
|
+
return []
|
|
124
|
+
return value if isinstance(value, list) else [value]
|
|
125
|
+
|
|
126
|
+
|
|
55
127
|
RESPONSE_CODES = {
|
|
56
128
|
1: "Approved",
|
|
57
129
|
2: "Declined",
|
|
@@ -567,7 +639,9 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
567
639
|
Pre-authorize a payment using authOnlyTransaction on a stored profile.
|
|
568
640
|
|
|
569
641
|
Authorize.Net authorizations expire after 30 days. No HTTP response
|
|
570
|
-
raises ``ProcessorOutcomeUnknown`` with the side effect marked.
|
|
642
|
+
raises ``ProcessorOutcomeUnknown`` with the side effect marked. The
|
|
643
|
+
reference, when given, is sent as ``order.invoiceNumber`` and ``refId``
|
|
644
|
+
as in :meth:`charge_stored_payment_method`.
|
|
571
645
|
"""
|
|
572
646
|
amount_cents = _require_amount(
|
|
573
647
|
"authorize_net", payment_data["amount"], "amount"
|
|
@@ -584,17 +658,25 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
584
658
|
tx_request.amount = amount_dollars
|
|
585
659
|
tx_request.profile = profile
|
|
586
660
|
|
|
587
|
-
|
|
661
|
+
invoice_number = _invoice_number(payment_data)
|
|
662
|
+
if (
|
|
663
|
+
payment_data.get("client_id")
|
|
664
|
+
or payment_data.get("description")
|
|
665
|
+
or invoice_number
|
|
666
|
+
):
|
|
588
667
|
order = apicontractsv1.orderType()
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
668
|
+
if invoice_number:
|
|
669
|
+
order.invoiceNumber = invoice_number
|
|
670
|
+
if payment_data.get("client_id") or payment_data.get("description"):
|
|
671
|
+
client_id = payment_data.get("client_id", "")
|
|
672
|
+
desc = payment_data.get("description", str(client_id))
|
|
673
|
+
order.description = str(desc)[:255]
|
|
592
674
|
tx_request.order = order
|
|
593
675
|
|
|
594
676
|
request = apicontractsv1.createTransactionRequest()
|
|
595
677
|
request.merchantAuthentication = self._merchant_auth()
|
|
596
678
|
request.transactionRequest = tx_request
|
|
597
|
-
request.refId = f"ref{int(time.time() * 1000)}"
|
|
679
|
+
request.refId = invoice_number or f"ref{int(time.time() * 1000)}"
|
|
598
680
|
|
|
599
681
|
controller = apicontrollers.createTransactionController(request)
|
|
600
682
|
except Exception as e:
|
|
@@ -614,6 +696,7 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
614
696
|
"customer_profile_id": payment_data.get("customer_profile_id"),
|
|
615
697
|
"payment_profile_id": payment_data.get("payment_method"),
|
|
616
698
|
"ref_id": request.refId,
|
|
699
|
+
"processor_reference": invoice_number,
|
|
617
700
|
},
|
|
618
701
|
)
|
|
619
702
|
trans = response.get("transactionResponse", {})
|
|
@@ -649,6 +732,8 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
649
732
|
}
|
|
650
733
|
if mirror_error:
|
|
651
734
|
metadata["mirror_error"] = mirror_error
|
|
735
|
+
if invoice_number:
|
|
736
|
+
metadata["processor_reference"] = invoice_number
|
|
652
737
|
return {
|
|
653
738
|
"processor_transaction_id": trans.get("transId"),
|
|
654
739
|
"status": "authorized",
|
|
@@ -667,7 +752,11 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
667
752
|
"authorization_code": None,
|
|
668
753
|
"expires_at": None,
|
|
669
754
|
"error_message": _transaction_error_text(trans, code),
|
|
670
|
-
"metadata":
|
|
755
|
+
"metadata": (
|
|
756
|
+
{"response_code": code, "processor_reference": invoice_number}
|
|
757
|
+
if invoice_number
|
|
758
|
+
else {"response_code": code}
|
|
759
|
+
),
|
|
671
760
|
}
|
|
672
761
|
|
|
673
762
|
def charge_stored_payment_method(
|
|
@@ -680,7 +769,17 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
680
769
|
and spot donations. No HTTP response raises ``ProcessorOutcomeUnknown``
|
|
681
770
|
(as before, this path raises rather than returns on transport errors)
|
|
682
771
|
with the side effect marked.
|
|
772
|
+
|
|
773
|
+
Authorize.Net has no idempotency keys. The stable business reference
|
|
774
|
+
(``payment_data["reference"]``, else ``["idempotency_key"]``) is sent
|
|
775
|
+
as ``order.invoiceNumber`` and as the request ``refId`` (both hashed
|
|
776
|
+
to 20 characters when longer) and returned in
|
|
777
|
+
``metadata["processor_reference"]`` (and in the
|
|
778
|
+
``ProcessorOutcomeUnknown`` metadata); :meth:`find_charge_by_reference`
|
|
779
|
+
finds the charge by it. Without a reference the ``refId`` stays
|
|
780
|
+
time-based.
|
|
683
781
|
"""
|
|
782
|
+
invoice_number = _invoice_number(payment_data)
|
|
684
783
|
try:
|
|
685
784
|
amount_cents = _require_amount(
|
|
686
785
|
"authorize_net", payment_data.get("amount"), "amount"
|
|
@@ -702,13 +801,16 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
702
801
|
client_id = payment_data.get("client_id", "")
|
|
703
802
|
campaign = metadata.get("campaign", str(client_id))
|
|
704
803
|
order_description = None
|
|
705
|
-
if client_id or campaign:
|
|
804
|
+
if client_id or campaign or invoice_number:
|
|
706
805
|
order = apicontractsv1.orderType()
|
|
806
|
+
if invoice_number:
|
|
807
|
+
order.invoiceNumber = invoice_number
|
|
707
808
|
if client_id and campaign:
|
|
708
809
|
order_description = f"{client_id}::{campaign}"[:255]
|
|
709
|
-
|
|
810
|
+
elif client_id or campaign:
|
|
710
811
|
order_description = str(client_id or campaign)[:255]
|
|
711
|
-
|
|
812
|
+
if order_description:
|
|
813
|
+
order.description = order_description
|
|
712
814
|
tx_request.order = order
|
|
713
815
|
|
|
714
816
|
# Line items
|
|
@@ -734,7 +836,7 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
734
836
|
request = apicontractsv1.createTransactionRequest()
|
|
735
837
|
request.merchantAuthentication = self._merchant_auth()
|
|
736
838
|
request.transactionRequest = tx_request
|
|
737
|
-
request.refId = f"ref{int(time.time() * 1000)}"
|
|
839
|
+
request.refId = invoice_number or f"ref{int(time.time() * 1000)}"
|
|
738
840
|
|
|
739
841
|
controller = apicontrollers.createTransactionController(request)
|
|
740
842
|
except ProcessorError:
|
|
@@ -752,7 +854,14 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
752
854
|
"platform_fee": 0,
|
|
753
855
|
"client_amount": 0,
|
|
754
856
|
"error_message": scrub(str(e)),
|
|
755
|
-
"metadata":
|
|
857
|
+
"metadata": (
|
|
858
|
+
{
|
|
859
|
+
"error_type": type(e).__name__,
|
|
860
|
+
"processor_reference": invoice_number,
|
|
861
|
+
}
|
|
862
|
+
if invoice_number
|
|
863
|
+
else {"error_type": type(e).__name__}
|
|
864
|
+
),
|
|
756
865
|
}
|
|
757
866
|
|
|
758
867
|
response = self._execute(
|
|
@@ -764,6 +873,7 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
764
873
|
"customer_profile_id": payment_data.get("customer_profile_id"),
|
|
765
874
|
"payment_profile_id": payment_data.get("payment_method"),
|
|
766
875
|
"ref_id": request.refId,
|
|
876
|
+
"processor_reference": invoice_number,
|
|
767
877
|
},
|
|
768
878
|
)
|
|
769
879
|
trans = response.get("transactionResponse", {})
|
|
@@ -807,6 +917,8 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
807
917
|
}
|
|
808
918
|
if mirror_error:
|
|
809
919
|
result_metadata["mirror_error"] = mirror_error
|
|
920
|
+
if invoice_number:
|
|
921
|
+
result_metadata["processor_reference"] = invoice_number
|
|
810
922
|
return {
|
|
811
923
|
"processor_transaction_id": trans.get("transId"),
|
|
812
924
|
"processor_charge_id": trans.get("transId"),
|
|
@@ -831,7 +943,187 @@ class AuthorizeNetAdapter(PaymentProcessorAdapter):
|
|
|
831
943
|
"platform_fee": 0,
|
|
832
944
|
"client_amount": 0,
|
|
833
945
|
"error_message": _transaction_error_text(trans, code),
|
|
834
|
-
"metadata":
|
|
946
|
+
"metadata": (
|
|
947
|
+
{"response_code": code, "processor_reference": invoice_number}
|
|
948
|
+
if invoice_number
|
|
949
|
+
else {"response_code": code}
|
|
950
|
+
),
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
# ========================================================================
|
|
954
|
+
# LOOKUP BY REFERENCE
|
|
955
|
+
# ========================================================================
|
|
956
|
+
|
|
957
|
+
def find_charge_by_reference(
|
|
958
|
+
self,
|
|
959
|
+
tx,
|
|
960
|
+
reference: str,
|
|
961
|
+
*,
|
|
962
|
+
amount: Optional[int] = None,
|
|
963
|
+
since: Optional[datetime] = None,
|
|
964
|
+
) -> Optional[Dict[str, Any]]:
|
|
965
|
+
"""Find the live transaction whose ``invoiceNumber`` is ``reference``.
|
|
966
|
+
|
|
967
|
+
Authorize.Net cannot search by invoice number, so this scans the
|
|
968
|
+
documented reporting lists and filters on ``invoiceNumber`` (the same
|
|
969
|
+
20-character fitting the charge applied):
|
|
970
|
+
|
|
971
|
+
* ``getUnsettledTransactionListRequest`` (status ``any``, so held
|
|
972
|
+
transactions are included), sorted by ``submitTimeUTC``, paged 1000
|
|
973
|
+
at a time;
|
|
974
|
+
* ``getSettledBatchListRequest`` from ``since`` to now (in 30-day
|
|
975
|
+
windows; the API allows 31), then ``getTransactionListRequest`` per
|
|
976
|
+
batch, sorted and paged the same way.
|
|
977
|
+
|
|
978
|
+
``since`` bounds the scan (default: 31 days back) -- pass the attempt's
|
|
979
|
+
creation time. Each request is a Transaction Details API call, so the
|
|
980
|
+
scan costs one call per batch page. Declined, voided, expired, error
|
|
981
|
+
and refund transactions are ignored; a transaction under fraud review
|
|
982
|
+
is returned with ``success=False``. The amount is the summary's
|
|
983
|
+
``settleAmount``. Any API error or missing response raises
|
|
984
|
+
``ProcessorOutcomeUnknown``. Transaction Details API access must be
|
|
985
|
+
enabled for the API login.
|
|
986
|
+
|
|
987
|
+
``status`` uses the charge path's vocabulary: ``"Approved"``,
|
|
988
|
+
``"Held for Review"`` (fraud review, ``success=False``) or
|
|
989
|
+
``"authorized"`` (an uncaptured authOnly); the raw value is in
|
|
990
|
+
``metadata["transaction_status"]``. The found transaction is mirrored
|
|
991
|
+
to ``authorize_transactions`` with the charge path's writer (an
|
|
992
|
+
idempotent upsert keyed by ``remote_transid``); a mirror failure does
|
|
993
|
+
not hide the charge and sets ``metadata["mirror_error"]``.
|
|
994
|
+
"""
|
|
995
|
+
reference = self._require_reference(reference)
|
|
996
|
+
invoice_number = fit_reference(reference, INVOICE_NUMBER_MAX_LENGTH)
|
|
997
|
+
now = datetime.now(timezone.utc)
|
|
998
|
+
start = _as_utc(since) or now - DEFAULT_REFERENCE_LOOKBACK
|
|
999
|
+
found: Dict[str, Dict[str, Any]] = {}
|
|
1000
|
+
try:
|
|
1001
|
+
for summary in self._unsettled_transactions():
|
|
1002
|
+
if summary.get("invoiceNumber") == invoice_number:
|
|
1003
|
+
found.setdefault(str(summary.get("transId")), summary)
|
|
1004
|
+
for batch_id in self._settled_batch_ids(start, now):
|
|
1005
|
+
for summary in self._batch_transactions(batch_id):
|
|
1006
|
+
if summary.get("invoiceNumber") == invoice_number:
|
|
1007
|
+
found.setdefault(str(summary.get("transId")), summary)
|
|
1008
|
+
except Exception as exc:
|
|
1009
|
+
raise self._reference_lookup_failed(reference, exc) from None
|
|
1010
|
+
|
|
1011
|
+
matches = [
|
|
1012
|
+
self._normalize_summary(summary, invoice_number)
|
|
1013
|
+
for summary in found.values()
|
|
1014
|
+
if summary.get("transactionStatus") not in _DEAD_STATUSES
|
|
1015
|
+
]
|
|
1016
|
+
match = self._select_reference_match(reference, matches, amount)
|
|
1017
|
+
if match is None:
|
|
1018
|
+
return None
|
|
1019
|
+
summary = match["metadata"]["transaction_summary"]
|
|
1020
|
+
status = match["status"]
|
|
1021
|
+
mirror_error = self._mirror_transaction(
|
|
1022
|
+
tx,
|
|
1023
|
+
{
|
|
1024
|
+
"processor_transaction_id": match["processor_transaction_id"],
|
|
1025
|
+
"amount": (
|
|
1026
|
+
cents_to_decimal(match["amount"])
|
|
1027
|
+
if match["amount"] is not None
|
|
1028
|
+
else None
|
|
1029
|
+
),
|
|
1030
|
+
"status": status,
|
|
1031
|
+
"remote_responsecode": 4 if status == RESPONSE_CODES[4] else 1,
|
|
1032
|
+
"raw_payload": summary,
|
|
1033
|
+
},
|
|
1034
|
+
"find_charge_by_reference",
|
|
1035
|
+
)
|
|
1036
|
+
if mirror_error:
|
|
1037
|
+
match["metadata"]["mirror_error"] = mirror_error
|
|
1038
|
+
return match
|
|
1039
|
+
|
|
1040
|
+
def _paged_transactions(self, build_request, make_controller):
|
|
1041
|
+
"""Yield transaction summaries page by page (sorted, 1000 per page)."""
|
|
1042
|
+
page = 1
|
|
1043
|
+
while True:
|
|
1044
|
+
request = build_request()
|
|
1045
|
+
request.merchantAuthentication = self._merchant_auth()
|
|
1046
|
+
sorting = apicontractsv1.TransactionListSorting()
|
|
1047
|
+
sorting.orderBy = apicontractsv1.TransactionListOrderFieldEnum.submitTimeUTC
|
|
1048
|
+
sorting.orderDescending = False
|
|
1049
|
+
request.sorting = sorting
|
|
1050
|
+
paging = apicontractsv1.Paging()
|
|
1051
|
+
paging.limit = _PAGE_LIMIT
|
|
1052
|
+
paging.offset = page
|
|
1053
|
+
request.paging = paging
|
|
1054
|
+
response = self._execute(make_controller(request))
|
|
1055
|
+
items = _as_list(response.get("transactions"), "transaction")
|
|
1056
|
+
yield from items
|
|
1057
|
+
if len(items) < _PAGE_LIMIT:
|
|
1058
|
+
return
|
|
1059
|
+
page += 1
|
|
1060
|
+
|
|
1061
|
+
def _unsettled_transactions(self):
|
|
1062
|
+
def build():
|
|
1063
|
+
request = apicontractsv1.getUnsettledTransactionListRequest()
|
|
1064
|
+
request.status = apicontractsv1.TransactionGroupStatusEnum.any
|
|
1065
|
+
return request
|
|
1066
|
+
|
|
1067
|
+
return self._paged_transactions(
|
|
1068
|
+
build, apicontrollers.getUnsettledTransactionListController
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
def _batch_transactions(self, batch_id: str):
|
|
1072
|
+
def build():
|
|
1073
|
+
request = apicontractsv1.getTransactionListRequest()
|
|
1074
|
+
request.batchId = batch_id
|
|
1075
|
+
return request
|
|
1076
|
+
|
|
1077
|
+
return self._paged_transactions(
|
|
1078
|
+
build, apicontrollers.getTransactionListController
|
|
1079
|
+
)
|
|
1080
|
+
|
|
1081
|
+
def _settled_batch_ids(self, start: datetime, end: datetime) -> List[str]:
|
|
1082
|
+
"""Settled batch ids from ``start`` to ``end``, 30 days per request."""
|
|
1083
|
+
batch_ids: List[str] = []
|
|
1084
|
+
window_start = start
|
|
1085
|
+
while window_start < end:
|
|
1086
|
+
window_end = min(window_start + _BATCH_WINDOW, end)
|
|
1087
|
+
request = apicontractsv1.getSettledBatchListRequest()
|
|
1088
|
+
request.merchantAuthentication = self._merchant_auth()
|
|
1089
|
+
request.firstSettlementDate = window_start
|
|
1090
|
+
request.lastSettlementDate = window_end
|
|
1091
|
+
response = self._execute(
|
|
1092
|
+
apicontrollers.getSettledBatchListController(request)
|
|
1093
|
+
)
|
|
1094
|
+
for batch in _as_list(response.get("batchList"), "batch"):
|
|
1095
|
+
batch_id = batch.get("batchId")
|
|
1096
|
+
if batch_id and batch_id not in batch_ids:
|
|
1097
|
+
batch_ids.append(batch_id)
|
|
1098
|
+
window_start = window_end
|
|
1099
|
+
return batch_ids
|
|
1100
|
+
|
|
1101
|
+
@staticmethod
|
|
1102
|
+
def _normalize_summary(
|
|
1103
|
+
summary: Dict[str, Any], invoice_number: str
|
|
1104
|
+
) -> Dict[str, Any]:
|
|
1105
|
+
"""A transactionSummaryType (as a dict) in the charge result shape."""
|
|
1106
|
+
raw_status = summary.get("transactionStatus")
|
|
1107
|
+
settle_amount = summary.get("settleAmount")
|
|
1108
|
+
amount_cents = to_cents(str(settle_amount)) if settle_amount else None
|
|
1109
|
+
return {
|
|
1110
|
+
"processor_transaction_id": summary.get("transId"),
|
|
1111
|
+
"processor_charge_id": summary.get("transId"),
|
|
1112
|
+
"status": _lookup_status(raw_status),
|
|
1113
|
+
"success": raw_status not in _PENDING_STATUSES,
|
|
1114
|
+
"amount": amount_cents,
|
|
1115
|
+
"currency": "usd",
|
|
1116
|
+
"authorization_code": None, # not in the summary; see get_transaction_details
|
|
1117
|
+
"platform_fee": 0,
|
|
1118
|
+
"client_amount": amount_cents,
|
|
1119
|
+
"created_at": summary.get("submitTimeUTC"),
|
|
1120
|
+
"error_message": None,
|
|
1121
|
+
"metadata": {
|
|
1122
|
+
"processor_reference": invoice_number,
|
|
1123
|
+
"found_by_reference": True,
|
|
1124
|
+
"transaction_status": raw_status,
|
|
1125
|
+
"transaction_summary": summary,
|
|
1126
|
+
},
|
|
835
1127
|
}
|
|
836
1128
|
|
|
837
1129
|
# ========================================================================
|